da9d2a758e494c5eeffdd81c0be43fdeecc10679
[mono.git] / mcs / class / System.Web / System.Web.UI / ClientScriptManager.cs
1 //
2 // System.Web.UI.ClientScriptManager.cs
3 //
4 // Authors:
5 //   Duncan Mak  (duncan@ximian.com)
6 //   Gonzalo Paniagua (gonzalo@ximian.com)
7 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 //   Lluis Sanchez (lluis@novell.com)
9 //
10 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
11 // (c) 2003 Novell, Inc. (http://www.novell.com)
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Collections;
37 using System.Text;
38
39 namespace System.Web.UI
40 {
41         #if NET_2_0
42         public sealed
43         #else
44         internal
45         #endif
46                 class ClientScriptManager
47         {
48                 Hashtable registeredArrayDeclares;
49                 ScriptEntry clientScriptBlocks;
50                 ScriptEntry startupScriptBlocks;
51                 Hashtable hiddenFields;
52                 ScriptEntry submitStatements;
53                 ScriptEntry scriptIncludes;
54                 Page page;
55         
56                 internal ClientScriptManager (Page page)
57                 {
58                         this.page = page;
59                 }
60
61 #if !NET_2_0
62                 public string GetPostBackClientEvent (Control control, string argument)
63                 {
64                         return GetPostBackEventReference (control, argument);
65                 }
66 #endif
67
68                 public string GetPostBackClientHyperlink (Control control, string argument)
69                 {
70                         return "javascript:" + GetPostBackEventReference (control, argument);
71                 }
72         
73                 public string GetPostBackEventReference (Control control, string argument)
74                 {
75                         page.RequiresPostBackScript ();
76                         return String.Format ("__doPostBack('{0}','{1}')", control.UniqueID, argument);
77                 }
78                 
79 #if NET_2_0
80                 public string GetPostBackEventReference (PostBackOptions options)
81                 {
82                         if (options.ActionUrl == null && options.ValidationGroup == null && !options.TrackFocus && 
83                                 !options.AutoPostBack && !options.PerformValidation)
84                         {
85                                 if (!options.ClientSubmit)
86                                         return null;
87
88                                 if (options.RequiresJavaScriptProtocol)
89                                         return GetPostBackClientHyperlink (options.TargetControl, options.Argument);
90                                 else
91                                         return GetPostBackEventReference (options.TargetControl, options.Argument);
92                         }
93                         
94                         if (!IsClientScriptIncludeRegistered (typeof(Page), "webform")) {
95                                 RegisterClientScriptInclude (typeof(Page), "webform", GetWebResourceUrl (typeof(Page), "webform.js"));
96                         }
97                         
98                         if (options.ActionUrl != null)
99                                 RegisterHiddenField (Page.PreviousPageID, page.Request.FilePath);
100                         
101                         if (options.ClientSubmit || options.ActionUrl != null)
102                                 page.RequiresPostBackScript ();
103                         
104                         return String.Format ("{0}WebForm_DoPostback({1},{2},{3},{4},{5},{6},{7},{8})", 
105                                         options.RequiresJavaScriptProtocol ? "javascript:" : "",
106                                         ClientScriptManager.GetScriptLiteral (options.TargetControl.UniqueID), 
107                                         ClientScriptManager.GetScriptLiteral (options.Argument),
108                                         ClientScriptManager.GetScriptLiteral (options.ActionUrl),
109                                         ClientScriptManager.GetScriptLiteral (options.AutoPostBack),
110                                         ClientScriptManager.GetScriptLiteral (options.PerformValidation),
111                                         ClientScriptManager.GetScriptLiteral (options.TrackFocus),
112                                         ClientScriptManager.GetScriptLiteral (options.ClientSubmit),
113                                         ClientScriptManager.GetScriptLiteral (options.ValidationGroup)
114                                 );
115                 }
116                 
117                 public string GetCallbackEventReference (Control control, string argument, string clientCallback, string context)
118                 {
119                         return GetCallbackEventReference (control, argument, clientCallback, context, null, false);
120                 }
121
122                 public string GetCallbackEventReference (Control control, string argument, string clientCallback, string context, bool useAsync)
123                 {
124                         return GetCallbackEventReference (control, argument, clientCallback, context, null, useAsync);
125                 }
126
127                 public string GetCallbackEventReference (Control control, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)
128                 {
129                         if (control == null)
130                                 throw new ArgumentNullException ("control");
131                         if(!(control is ICallbackEventHandler))
132                                 throw new InvalidOperationException ("The control must implement the ICallbackEventHandler interface and provide a RaiseCallbackEvent method.");
133
134                         return GetCallbackEventReference (control.UniqueID, argument, clientCallback, context, clientErrorCallback, useAsync);
135                 }
136
137                 public string GetCallbackEventReference (string target, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)
138                 {
139                         page.RequiresPostBackScript ();
140
141                         if (!IsClientScriptIncludeRegistered (typeof(Page), "callback"))
142                                 RegisterClientScriptInclude (typeof(Page), "callback", GetWebResourceUrl (typeof(Page), "callback.js"));
143                         
144                         return string.Format ("WebForm_DoCallback('{0}',{1},{2},{3},{4},{5})", target, argument, clientCallback, context, ((clientErrorCallback == null) ? "null" : clientErrorCallback), (useAsync ? "true" : "false"));
145                 }
146 #endif
147                 
148 #if NET_2_0
149                 public
150 #else
151                 internal
152 #endif
153                 string GetWebResourceUrl(Type type, string resourceName)
154                 {
155                         if (type == null)
156                                 throw new ArgumentNullException ("type");
157                 
158                         if (resourceName == null || resourceName.Length == 0)
159                                 throw new ArgumentNullException ("type");
160                 
161                         return System.Web.Handlers.AssemblyResourceLoader.GetResourceUrl (type, resourceName); 
162                 }
163                 
164
165                 public bool IsClientScriptBlockRegistered (string key)
166                 {
167                         return IsScriptRegistered (clientScriptBlocks, GetType(), key);
168                 }
169         
170                 public bool IsClientScriptBlockRegistered (Type type, string key)
171                 {
172                         return IsScriptRegistered (clientScriptBlocks, type, key);
173                 }
174         
175                 public bool IsStartupScriptRegistered (string key)
176                 {
177                         return IsScriptRegistered (startupScriptBlocks, GetType(), key);
178                 }
179         
180                 public bool IsStartupScriptRegistered (Type type, string key)
181                 {
182                         return IsScriptRegistered (startupScriptBlocks, type, key);
183                 }
184                 
185                 public bool IsOnSubmitStatementRegistered (string key)
186                 {
187                         return IsScriptRegistered (submitStatements, GetType(), key);
188                 }
189         
190                 public bool IsOnSubmitStatementRegistered (Type type, string key)
191                 {
192                         return IsScriptRegistered (submitStatements, type, key);
193                 }
194                 
195                 public bool IsClientScriptIncludeRegistered (string key)
196                 {
197                         return IsScriptRegistered (scriptIncludes, GetType(), key);
198                 }
199         
200                 public bool IsClientScriptIncludeRegistered (Type type, string key)
201                 {
202                         return IsScriptRegistered (scriptIncludes, type, key);
203                 }
204                 
205                 bool IsScriptRegistered (ScriptEntry scriptList, Type type, string key)
206                 {
207                         while (scriptList != null) {
208                                 if (scriptList.Type == type && scriptList.Key == key)
209                                         return true;
210                                 scriptList = scriptList.Next;
211                         }
212                         return false;
213                 }
214                 
215                 public void RegisterArrayDeclaration (string arrayName, string arrayValue)
216                 {
217                         if (registeredArrayDeclares == null)
218                                 registeredArrayDeclares = new Hashtable();
219         
220                         if (!registeredArrayDeclares.ContainsKey (arrayName))
221                                 registeredArrayDeclares.Add (arrayName, new ArrayList());
222         
223                         ((ArrayList) registeredArrayDeclares[arrayName]).Add(arrayValue);
224                 }
225         
226                 void RegisterScript (ref ScriptEntry scriptList, Type type, string key, string script, bool addScriptTags)
227                 {
228                         ScriptEntry last = null;
229                         ScriptEntry entry = scriptList;
230
231                         while (entry != null) {
232                                 if (entry.Type == type && entry.Key == key)
233                                         return;
234                                 last = entry;
235                                 entry = entry.Next;
236                         }
237                         
238                         if (addScriptTags)
239                                 script = "<script language=javascript>\n<!--\n" + script + "\n// -->\n</script>";
240
241                         entry = new ScriptEntry (type, key, script);
242                         
243                         if (last != null) last.Next = entry;
244                         else scriptList = entry;
245                 }
246         
247                 internal void RegisterClientScriptBlock (string key, string script)
248                 {
249                         RegisterScript (ref clientScriptBlocks, GetType(), key, script, false);
250                 }
251         
252                 public void RegisterClientScriptBlock (Type type, string key, string script)
253                 {
254                         RegisterClientScriptBlock (type, key, script, false);
255                 }
256         
257                 public void RegisterClientScriptBlock (Type type, string key, string script, bool addScriptTags)
258                 {
259                         if (type == null)
260                                 throw new ArgumentNullException ("type");
261
262                         RegisterScript (ref clientScriptBlocks, type, key, script, addScriptTags);
263                 }
264         
265                 public void RegisterHiddenField (string hiddenFieldName, string hiddenFieldInitialValue)
266                 {
267                         if (hiddenFields == null)
268                                 hiddenFields = new Hashtable ();
269
270                         if (!hiddenFields.ContainsKey (hiddenFieldName))
271                                 hiddenFields.Add (hiddenFieldName, hiddenFieldInitialValue);
272                 }
273         
274                 internal void RegisterOnSubmitStatement (string key, string script)
275                 {
276                         RegisterScript (ref submitStatements, GetType (), key, script, false);
277                 }
278         
279                 public void RegisterOnSubmitStatement (Type type, string key, string script)
280                 {
281                         if (type == null)
282                                 throw new ArgumentNullException ("type");
283                         
284                         RegisterScript (ref submitStatements, type, key, script, false);
285                 }
286         
287                 internal void RegisterStartupScript (string key, string script)
288                 {
289                         RegisterScript (ref startupScriptBlocks, GetType(), key, script, false);
290                 }
291                 
292                 public void RegisterStartupScript (Type type, string key, string script)
293                 {
294                         RegisterStartupScript (type, key, script, false);
295                 }
296                 
297                 public void RegisterStartupScript (Type type, string key, string script, bool addScriptTags)
298                 {
299                         if (type == null)
300                                 throw new ArgumentNullException ("type");
301
302                         RegisterScript (ref startupScriptBlocks, type, key, script, addScriptTags);
303                 }
304
305                 public void RegisterClientScriptInclude (string key, string url)
306                 {
307                         RegisterClientScriptInclude (GetType (), key, url);
308                 }
309                 
310                 public void RegisterClientScriptInclude (Type type, string key, string url)
311                 {
312                         if (type == null)
313                                 throw new ArgumentNullException ("type");
314                         if (url == null || url.Length == 0)
315                                 throw new ArgumentException ("url");
316
317                         RegisterScript (ref scriptIncludes, type, key, url, false);
318                 }
319
320 #if NET_2_0
321                 public void RegisterClientScriptResource (Type type, string resourceName)
322                 {
323                         RegisterScript (ref scriptIncludes, type, "resource-" + resourceName, GetWebResourceUrl (type, resourceName), false);
324                 }
325
326                 [MonoTODO]
327                 public void RegisterExpandoAttribute (string controlId, 
328                                                       string name, 
329                                                       string value)
330                 {
331                         throw new NotImplementedException ();
332                 }
333
334                 [MonoTODO]
335                 public void RegisterExpandoAttribute(string controlId, 
336                                                      string attributeName, 
337                                                      string attributeValue, 
338                                                      bool encode)
339                 {
340                         throw new NotImplementedException ();
341                 }
342
343                 [MonoTODO]
344                 public void RegisterForEventValidation (PostBackOptions options)
345                 {
346                         throw new NotImplementedException ();
347                 }
348                 
349                 [MonoTODO]
350                 public void RegisterForEventValidation (string uniqueId)
351                 {
352                         throw new NotImplementedException ();
353                 }
354
355                 [MonoTODO]
356                 public void RegisterForEventValidation (string uniqueId, string argument)
357                 {
358                         throw new NotImplementedException ();
359                 }
360
361                 [MonoTODO]
362                 public void ValidateEvent (string uniqueId)
363                 {
364                         throw new NotImplementedException ();
365                 }
366
367                 [MonoTODO]
368                 public void ValidateEvent (string uniqueId, string argument)
369                 {
370                         throw new NotImplementedException ();
371                 }
372 #endif
373                 void WriteScripts (HtmlTextWriter writer, ScriptEntry scriptList)
374                 {
375                         while (scriptList != null) {
376                                 writer.WriteLine (scriptList.Script);
377                                 scriptList = scriptList.Next;
378                         }
379                 }
380                 
381                 internal void WriteHiddenFields (HtmlTextWriter writer)
382                 {
383                         if (hiddenFields == null)
384                                 return;
385         
386                         foreach (string key in hiddenFields.Keys) {
387                                 string value = hiddenFields [key] as string;
388                                 writer.WriteLine ("\n<input type=\"hidden\" name=\"{0}\" id=\"{0}\" value=\"{1}\" />", key, value);
389                         }
390         
391                         hiddenFields = null;
392                 }
393                 
394                 internal void WriteClientScriptIncludes (HtmlTextWriter writer)
395                 {
396                         ScriptEntry entry = scriptIncludes;
397                         while (entry != null) {
398                                 writer.WriteLine ("\n<script src=\"{0}\" type=\"text/javascript\"></script>", entry.Script);
399                                 entry = entry.Next;
400                         }
401                 }
402                 
403                 internal void WriteClientScriptBlocks (HtmlTextWriter writer)
404                 {
405                         WriteScripts (writer, clientScriptBlocks);
406                 }
407         
408                 internal void WriteStartupScriptBlocks (HtmlTextWriter writer)
409                 {
410                         WriteScripts (writer, startupScriptBlocks);
411                 }
412         
413                 internal void WriteArrayDeclares (HtmlTextWriter writer)
414                 {
415                         if (registeredArrayDeclares != null) {
416                                 writer.WriteLine();
417                                 writer.WriteLine("<script language=\"javascript\">");
418                                 writer.WriteLine("<!--");
419                                 IDictionaryEnumerator arrayEnum = registeredArrayDeclares.GetEnumerator();
420                                 while (arrayEnum.MoveNext()) {
421                                         writer.Write("\tvar ");
422                                         writer.Write(arrayEnum.Key);
423                                         writer.Write(" =  new Array(");
424                                         IEnumerator arrayListEnum = ((ArrayList) arrayEnum.Value).GetEnumerator();
425                                         bool isFirst = true;
426                                         while (arrayListEnum.MoveNext()) {
427                                                 if (isFirst)
428                                                         isFirst = false;
429                                                 else
430                                                         writer.Write(", ");
431                                                 writer.Write(arrayListEnum.Current);
432                                         }
433                                         writer.WriteLine(");");
434                                 }
435                                 writer.WriteLine("// -->");
436                                 writer.WriteLine("</script>");
437                                 writer.WriteLine();
438                         }
439                 }
440
441 #if NET_2_0
442                 internal string GetClientValidationEvent (string validationGroup) {
443                         return "if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate('" + validationGroup + "');";
444                 }
445 #endif
446
447                 internal string GetClientValidationEvent ()
448                 {
449                         return "if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate();";
450                 }
451
452
453                 internal string WriteSubmitStatements ()
454                 {
455                         if (submitStatements == null) return null;
456                         
457                         StringBuilder sb = new StringBuilder ();
458                         ScriptEntry entry = submitStatements;
459                         while (entry != null) {
460                                 sb.Append (entry.Script);
461                                 entry = entry.Next;
462                         }
463                         return sb.ToString ();
464                 }
465                 
466                 internal static string GetScriptLiteral (object ob)
467                 {
468                         if (ob == null)
469                                 return "null";
470                         else if (ob is string) {
471                                 string s = (string)ob;
472                                 s = s.Replace ("\"", "\\\"");
473                                 return "\"" + s + "\"";
474                         } else if (ob is bool) {
475                                 return ob.ToString().ToLower();
476                         } else {
477                                 return ob.ToString ();
478                         }
479                 }
480                 
481                 class ScriptEntry
482                 {
483                         public Type Type;
484                         public string Key;
485                         public string Script;
486                         public ScriptEntry Next;
487                          
488                         public ScriptEntry (Type type, string key, string script)
489                         {
490                                 Key = key;
491                                 Type = type;
492                                 Script = script;
493                         }
494                 }
495
496 #if NET_2_0
497                 // helper method
498                 internal static string EnsureEndsWithSemicolon (string value) {
499                         if (value != null && value.Length > 0 && !value.EndsWith (";"))
500                                 return value += ";";
501                         return value;
502                 }
503 #endif
504         }
505 }