]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/Web/UI/TClientScriptManager.php
cc59292a628374e21c2fd26023bfdacdc3aeef88
[bacula/bacula] / gui / baculum / framework / Web / UI / TClientScriptManager.php
1 <?php
2 /**
3  * TClientScriptManager and TClientSideOptions class file.
4  *
5  * @author Qiang Xue <qiang.xue@gmail.com>
6  * @author Gabor Berczi <gabor.berczi@devworx.hu> (lazyload additions & progressive rendering)
7  * @link http://www.pradosoft.com/
8  * @copyright Copyright &copy; 2005-2014 PradoSoft
9  * @license http://www.pradosoft.com/license/
10  * @package System.Web.UI
11  */
12
13 /**
14  * TClientScriptManager class.
15  *
16  * TClientScriptManager manages javascript and CSS stylesheets for a page.
17  *
18  * @author Qiang Xue <qiang.xue@gmail.com>
19  * @author Gabor Berczi <gabor.berczi@devworx.hu> (lazyload additions & progressive rendering)
20  * @package System.Web.UI
21  * @since 3.0
22  */
23 class TClientScriptManager extends TApplicationComponent
24 {
25         /**
26          * directory containing Prado javascript files
27          */
28         const SCRIPT_PATH='Web/Javascripts/source';
29         /**
30          * file containing javascript packages and their cross dependencies
31          */
32         const PACKAGES_FILE='Web/Javascripts/packages.php';
33         /**
34          * @var TPage page who owns this manager
35          */
36         private $_page;
37         /**
38          * @var array registered hidden fields, indexed by hidden field names
39          */
40         private $_hiddenFields=array();
41         /**
42          * @var array javascript blocks to be rendered at the beginning of the form
43          */
44         private $_beginScripts=array();
45         /**
46          * @var array javascript blocks to be rendered at the end of the form
47          */
48         private $_endScripts=array();
49         /**
50          * @var array javascript files to be rendered in the form
51          */
52         private $_scriptFiles=array();
53         /**
54          * @var array javascript files to be rendered in page head section
55          */
56         private $_headScriptFiles=array();
57         /**
58          * @var array javascript blocks to be rendered in page head section
59          */
60         private $_headScripts=array();
61         /**
62          * @var array CSS files
63          */
64         private $_styleSheetFiles=array();
65         /**
66          * @var array CSS declarations
67          */
68         private $_styleSheets=array();
69         /**
70          * @var array registered PRADO script libraries
71          */
72         private $_registeredPradoScripts=array();
73         /**
74          * Client-side javascript library dependencies, loads from PACKAGES_FILE;
75          * @var array
76          */
77         private static $_pradoScripts;
78         /**
79          * Client-side javascript library packages, loads from PACKAGES_FILE;
80          * @var array
81          */
82         private static $_pradoPackages;
83
84         private $_renderedHiddenFields;
85
86         private $_renderedScriptFiles=array();
87
88         private $_expandedPradoScripts;
89
90         /**
91          * Constructor.
92          * @param TPage page that owns this client script manager
93          */
94         public function __construct(TPage $owner)
95         {
96                 $this->_page=$owner;
97         }
98
99         /**
100          * @return boolean whether THead is required in order to render CSS and js within head
101          * @since 3.1.1
102          */
103         public function getRequiresHead()
104         {
105                 return count($this->_styleSheetFiles) || count($this->_styleSheets)
106                         || count($this->_headScriptFiles) || count($this->_headScripts);
107         }
108
109         public static function getPradoPackages()
110         {
111                 return self::$_pradoPackages;
112         }
113
114         public static function getPradoScripts()
115         {
116                 return self::$_pradoScripts;
117         }
118
119         /**
120          * Registers Prado javascript by library name. See "Web/Javascripts/packages.php"
121          * for library names.
122          * @param string script library name.
123          */
124         public function registerPradoScript($name)
125         {
126                 $this->registerPradoScriptInternal($name);
127                 $params=func_get_args();
128                 $this->_page->registerCachingAction('Page.ClientScript','registerPradoScript',$params);
129         }
130
131         /**
132          * Registers a Prado javascript library to be loaded.
133          */
134         protected function registerPradoScriptInternal($name)
135         {
136                 // $this->checkIfNotInRender();
137                 if(!isset($this->_registeredPradoScripts[$name]))
138                 {
139                         if(self::$_pradoScripts === null)
140                         {
141                                 $packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::PACKAGES_FILE;
142                                 list($packages,$deps)= include($packageFile);
143                                 self::$_pradoScripts = $deps;
144                                 self::$_pradoPackages = $packages;
145                         }
146
147                         if (isset(self::$_pradoScripts[$name]))
148                                 $this->_registeredPradoScripts[$name]=true;
149                         else
150                                 throw new TInvalidOperationException('csmanager_pradoscript_invalid',$name);
151
152                         if(($packages=array_keys($this->_registeredPradoScripts))!==array())
153                         {
154                                 $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;
155                                 list($path,$baseUrl)=$this->getPackagePathUrl($base);
156                                 $packagesUrl=array();
157                                 $isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug;
158                                 foreach ($packages as $p)
159                                 {
160                                         foreach (self::$_pradoScripts[$p] as $dep)
161                                         {
162                                                 foreach (self::$_pradoPackages[$dep] as $script)
163                                                 if (!isset($this->_expandedPradoScripts[$script]))
164                                                 {
165                                                         $this->_expandedPradoScripts[$script] = true;
166                                                         if($isDebug)
167                                                         {
168                                                                 if (!in_array($url=$baseUrl.'/'.$script,$packagesUrl))
169                                                                         $packagesUrl[]=$url;
170                                                         } else {
171                                                                 if (!in_array($url=$baseUrl.'/min/'.$script,$packagesUrl))
172                                                                 {
173                                                                         if(!is_file($filePath=$path.'/min/'.$script))
174                                                                         {
175                                                                                 $dirPath=dirname($filePath);
176                                                                                 if(!is_dir($dirPath))
177                                                                                         mkdir($dirPath, PRADO_CHMOD, true);
178                                                                                 file_put_contents($filePath, TJavaScript::JSMin(file_get_contents($base.'/'.$script)));
179                                                                                 chmod($filePath, PRADO_CHMOD);
180                                                                         }
181                                                                         $packagesUrl[]=$url;
182                                                                 }
183                                                         }
184                                                 }
185                                         }
186                                 }
187                                 foreach($packagesUrl as $url)
188                                         $this->registerScriptFile($url,$url);
189                         }
190                 }
191         }
192
193         /**
194          * @return string Prado javascript library base asset url.
195          */
196         public function getPradoScriptAssetUrl()
197         {
198                 $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;
199                 $assets = Prado::getApplication()->getAssetManager();
200                 return $assets->getPublishedUrl($base);
201         }
202
203         /**
204          * Returns the URLs of all script files referenced on the page
205          * @return array Combined list of all script urls used in the page
206          */
207         public function getScriptUrls()
208         {
209                 $scripts = array_values($this->_headScriptFiles);
210                 $scripts = array_merge($scripts, array_values($this->_scriptFiles));
211                 $scripts = array_unique($scripts);
212
213                 return $scripts;
214         }
215
216         /**
217          * @param string javascript package path.
218          * @return array tuple($path,$url).
219          */
220         protected function getPackagePathUrl($base)
221         {
222                 $assets = Prado::getApplication()->getAssetManager();
223                 if(strpos($base, $assets->getBaseUrl())===false)
224                 {
225                         if(($dir = Prado::getPathOfNameSpace($base)) !== null) {
226                                 $base = $dir;
227                         }
228                         return array($assets->getPublishedPath($base), $assets->publishFilePath($base));
229                 }
230                 else
231                 {
232                         return array($assets->getBasePath().str_replace($assets->getBaseUrl(),'',$base), $base);
233                 }
234         }
235
236         /**
237          * Returns javascript statement that create a new callback request object.
238          * @param ICallbackEventHandler callback response handler
239          * @param array additional callback options
240          * @return string javascript statement that creates a new callback request.
241          */
242         public function getCallbackReference(ICallbackEventHandler $callbackHandler, $options=null)
243         {
244                 $options = !is_array($options) ? array() : $options;
245                 $class = new ReflectionClass($callbackHandler);
246                 $clientSide = $callbackHandler->getActiveControl()->getClientSide();
247                 $options = array_merge($options, $clientSide->getOptions()->toArray());
248                 $optionString = TJavaScript::encode($options);
249                 $this->registerPradoScriptInternal('ajax');
250                 $id = $callbackHandler->getUniqueID();
251                 return "new Prado.CallbackRequest('{$id}',{$optionString})";
252         }
253
254         /**
255          * Registers callback javascript for a control.
256          * @param string javascript class responsible for the control being registered for callback
257          * @param array callback options
258          */
259         public function registerCallbackControl($class, $options)
260         {
261                 $optionString=TJavaScript::encode($options);
262                 $code="new {$class}({$optionString});";
263                 $this->_endScripts[sprintf('%08X', crc32($code))]=$code;
264                 $this->registerPradoScriptInternal('ajax');
265
266                 $params=func_get_args();
267                 $this->_page->registerCachingAction('Page.ClientScript','registerCallbackControl',$params);
268         }
269
270         /**
271          * Registers postback javascript for a control. A null class parameter will prevent
272          * the javascript code registration.
273          * @param string javascript class responsible for the control being registered for postback
274          * @param array postback options
275          */
276         public function registerPostBackControl($class,$options)
277         {
278                 if($class === null) {
279                         return;
280                 }
281                 if(!isset($options['FormID']) && ($form=$this->_page->getForm())!==null)
282                         $options['FormID']=$form->getClientID();
283                 $optionString=TJavaScript::encode($options);
284                 $code="new {$class}({$optionString});";
285
286                 $this->_endScripts[sprintf('%08X', crc32($code))]=$code;
287                 $this->_hiddenFields[TPage::FIELD_POSTBACK_TARGET]='';
288                 $this->_hiddenFields[TPage::FIELD_POSTBACK_PARAMETER]='';
289                 $this->registerPradoScriptInternal('prado');
290
291                 $params=func_get_args();
292                 $this->_page->registerCachingAction('Page.ClientScript','registerPostBackControl',$params);
293         }
294
295         /**
296          * Register a default button to panel. When the $panel is in focus and
297          * the 'enter' key is pressed, the $button will be clicked.
298          * @param TControl|string panel (or its unique ID) to register the default button action
299          * @param TControl|string button (or its unique ID) to trigger a postback
300          */
301         public function registerDefaultButton($panel, $button)
302         {
303                 $panelID=is_string($panel)?$panel:$panel->getUniqueID();
304
305                 if(is_string($button))
306                         $buttonID=$button;
307                 else
308                 {
309                         $button->setIsDefaultButton(true);
310                         $buttonID=$button->getUniqueID();
311                 }
312                 $options = TJavaScript::encode($this->getDefaultButtonOptions($panelID, $buttonID));
313                 $code = "new Prado.WebUI.DefaultButton($options);";
314
315                 $this->_endScripts['prado:'.$panelID]=$code;
316                 $this->_hiddenFields[TPage::FIELD_POSTBACK_TARGET]='';
317                 $this->registerPradoScriptInternal('prado');
318
319                 $params=array($panelID,$buttonID);
320                 $this->_page->registerCachingAction('Page.ClientScript','registerDefaultButton',$params);
321         }
322
323         /**
324          * @param string the unique ID of the container control
325          * @param string the unique ID of the button control
326          * @return array default button options.
327          */
328         protected function getDefaultButtonOptions($panelID, $buttonID)
329         {
330                 $options['ID'] = TControl::convertUniqueIdToClientId($panelID);
331                 $options['Panel'] = TControl::convertUniqueIdToClientId($panelID);
332                 $options['Target'] = TControl::convertUniqueIdToClientId($buttonID);
333                 $options['EventTarget'] = $buttonID;
334                 $options['Event'] = 'click';
335                 return $options;
336         }
337
338         /**
339          * Registers the control to receive default focus.
340          * @param string the client ID of the control to receive default focus
341          */
342         public function registerFocusControl($target)
343         {
344                 $this->registerPradoScriptInternal('effects');
345                 if($target instanceof TControl)
346                         $target=$target->getClientID();
347                 $id = TJavaScript::quoteString($target);
348                 $this->_endScripts['prado:focus'] = 'Prado.Element.focus('.$id.');';
349
350                 $params=func_get_args();
351                 $this->_page->registerCachingAction('Page.ClientScript','registerFocusControl',$params);
352         }
353
354         /**
355          * Registers a CSS file to be rendered in the page head
356          *
357          * The CSS files in themes are registered in {@link OnPreRenderComplete onPreRenderComplete} if you want to override
358          * CSS styles in themes you need to register it after this event is completed.
359          *
360          * Example:
361          * <code>
362          * <?php
363          * class BasePage extends TPage {
364          *   public function onPreRenderComplete($param) {
365          *     parent::onPreRenderComplete($param);
366          *     $url = 'path/to/your/stylesheet.css';
367          *     $this->Page->ClientScript->registerStyleSheetFile($url, $url);
368          *   }
369          * }
370          * </code>
371          *
372          * @param string a unique key identifying the file
373          * @param string URL to the CSS file
374          * @param string media type of the CSS (such as 'print', 'screen', etc.). Defaults to empty, meaning the CSS applies to all media types.
375          */
376         public function registerStyleSheetFile($key,$url,$media='')
377         {
378                 if($media==='')
379                         $this->_styleSheetFiles[$key]=$url;
380                 else
381                         $this->_styleSheetFiles[$key]=array($url,$media);
382
383                 $params=func_get_args();
384                 $this->_page->registerCachingAction('Page.ClientScript','registerStyleSheetFile',$params);
385         }
386
387         /**
388          * Registers a CSS block to be rendered in the page head
389          * @param string a unique key identifying the CSS block
390          * @param string CSS block
391          */
392         public function registerStyleSheet($key,$css,$media='')
393         {
394                 $this->_styleSheets[$key]=$css;
395
396                 $params=func_get_args();
397                 $this->_page->registerCachingAction('Page.ClientScript','registerStyleSheet',$params);
398         }
399
400         /**
401          * Returns the URLs of all stylesheet files referenced on the page
402          * @return array List of all stylesheet urls used in the page
403          */
404         public function getStyleSheetUrls()
405         {
406                 $stylesheets = array_values(
407                         array_map(
408                                 create_function('$e', 'return is_array($e) ? $e[0] : $e;'),
409                                 $this->_styleSheetFiles)
410                 );
411
412                 foreach(Prado::getApplication()->getAssetManager()->getPublished() as $path=>$url)
413                         if (substr($url,strlen($url)-4)=='.css')
414                                 $stylesheets[] = $url;
415
416                 $stylesheets = array_unique($stylesheets);
417
418                 return $stylesheets;
419         }
420
421         /**
422          * Returns all the stylesheet code snippets referenced on the page
423          * @return array List of all stylesheet snippets used in the page
424          */
425         public function getStyleSheetCodes()
426         {
427                 return array_unique(array_values($this->_styleSheets));
428         }
429
430         /**
431          * Registers a javascript file in the page head
432          * @param string a unique key identifying the file
433          * @param string URL to the javascript file
434          */
435         public function registerHeadScriptFile($key,$url)
436         {
437                 $this->checkIfNotInRender();
438                 $this->_headScriptFiles[$key]=$url;
439
440                 $params=func_get_args();
441                 $this->_page->registerCachingAction('Page.ClientScript','registerHeadScriptFile',$params);
442         }
443
444         /**
445          * Registers a javascript block in the page head.
446          * @param string a unique key identifying the script block
447          * @param string javascript block
448          */
449         public function registerHeadScript($key,$script)
450         {
451                 $this->checkIfNotInRender();
452                 $this->_headScripts[$key]=$script;
453
454                 $params=func_get_args();
455                 $this->_page->registerCachingAction('Page.ClientScript','registerHeadScript',$params);
456         }
457
458         /**
459          * Registers a javascript file to be rendered within the form
460          * @param string a unique key identifying the file
461          * @param string URL to the javascript file to be rendered
462          */
463         public function registerScriptFile($key, $url)
464         {
465                 $this->_scriptFiles[$key]=$url;
466
467                 $params=func_get_args();
468                 $this->_page->registerCachingAction('Page.ClientScript','registerScriptFile',$params);
469         }
470
471         /**
472          * Registers a javascript script block at the beginning of the form
473          * @param string a unique key identifying the script block
474          * @param string javascript block
475          */
476         public function registerBeginScript($key,$script)
477         {
478                 $this->checkIfNotInRender();
479                 $this->_beginScripts[$key]=$script;
480
481                 $params=func_get_args();
482                 $this->_page->registerCachingAction('Page.ClientScript','registerBeginScript',$params);
483         }
484
485         /**
486          * Registers a javascript script block at the end of the form
487          * @param string a unique key identifying the script block
488          * @param string javascript block
489          */
490         public function registerEndScript($key,$script)
491         {
492                 $this->_endScripts[$key]=$script;
493
494                 $params=func_get_args();
495                 $this->_page->registerCachingAction('Page.ClientScript','registerEndScript',$params);
496         }
497
498         /**
499          * Registers a hidden field to be rendered in the form.
500          * @param string a unique key identifying the hidden field
501          * @param string|array hidden field value, if the value is an array, every element
502          * in the array will be rendered as a hidden field value.
503          */
504         public function registerHiddenField($name,$value)
505         {
506                 $this->_hiddenFields[$name]=$value;
507
508                 $params=func_get_args();
509                 $this->_page->registerCachingAction('Page.ClientScript','registerHiddenField',$params);
510         }
511
512         /**
513          * @param string a unique key
514          * @return boolean whether there is a CSS file registered with the specified key
515          */
516         public function isStyleSheetFileRegistered($key)
517         {
518                 return isset($this->_styleSheetFiles[$key]);
519         }
520
521         /**
522          * @param string a unique key
523          * @return boolean whether there is a CSS block registered with the specified key
524          */
525         public function isStyleSheetRegistered($key)
526         {
527                 return isset($this->_styleSheets[$key]);
528         }
529
530         /**
531          * @param string a unique key
532          * @return boolean whether there is a head javascript file registered with the specified key
533          */
534         public function isHeadScriptFileRegistered($key)
535         {
536                 return isset($this->_headScriptFiles[$key]);
537         }
538
539         /**
540          * @param string a unique key
541          * @return boolean whether there is a head javascript block registered with the specified key
542          */
543         public function isHeadScriptRegistered($key)
544         {
545                 return isset($this->_headScripts[$key]);
546         }
547
548         /**
549          * @param string a unique key
550          * @return boolean whether there is a javascript file registered with the specified key
551          */
552         public function isScriptFileRegistered($key)
553         {
554                 return isset($this->_scriptFiles[$key]);
555         }
556
557         /**
558          * @param string a unique key
559          * @return boolean whether there is a beginning javascript block registered with the specified key
560          */
561         public function isBeginScriptRegistered($key)
562         {
563                 return isset($this->_beginScripts[$key]);
564         }
565
566         /**
567          * @param string a unique key
568          * @return boolean whether there is an ending javascript block registered with the specified key
569          */
570         public function isEndScriptRegistered($key)
571         {
572                 return isset($this->_endScripts[$key]);
573         }
574
575         /**
576          * @return boolean true if any end scripts are registered.
577          */
578         public function hasEndScripts()
579         {
580                 return count($this->_endScripts) > 0;
581         }
582
583         /**
584          * @return boolean true if any begin scripts are registered.
585          */
586         public function hasBeginScripts()
587         {
588                 return count($this->_beginScripts) > 0;
589         }
590
591         /**
592          * @param string a unique key
593          * @return boolean whether there is a hidden field registered with the specified key
594          */
595         public function isHiddenFieldRegistered($key)
596         {
597                 return isset($this->_hiddenFields[$key]);
598         }
599
600         /**
601          * @param THtmlWriter writer for the rendering purpose
602          */
603         public function renderStyleSheetFiles($writer)
604         {
605                 $str='';
606                 foreach($this->_styleSheetFiles as $url)
607                 {
608                         if(is_array($url))
609                                 $str.="<link rel=\"stylesheet\" type=\"text/css\" media=\"{$url[1]}\" href=\"".THttpUtility::htmlEncode($url[0])."\" />\n";
610                         else
611                                 $str.="<link rel=\"stylesheet\" type=\"text/css\" href=\"".THttpUtility::htmlEncode($url)."\" />\n";
612                 }
613                 $writer->write($str);
614         }
615
616         /**
617          * @param THtmlWriter writer for the rendering purpose
618          */
619         public function renderStyleSheets($writer)
620         {
621                 if(count($this->_styleSheets))
622                         $writer->write("<style type=\"text/css\">\n/*<![CDATA[*/\n".implode("\n",$this->_styleSheets)."\n/*]]>*/\n</style>\n");
623         }
624
625         /**
626          * @param THtmlWriter writer for the rendering purpose
627          */
628         public function renderHeadScriptFiles($writer)
629         {
630                 $this->renderScriptFiles($writer,$this->_headScriptFiles);
631         }
632
633         /**
634          * @param THtmlWriter writer for the rendering purpose
635          */
636         public function renderHeadScripts($writer)
637         {
638                 $writer->write(TJavaScript::renderScriptBlocks($this->_headScripts));
639         }
640
641         public function renderScriptFilesBegin($writer)
642         {
643                 $this->renderAllPendingScriptFiles($writer);
644         }
645
646         public function renderScriptFilesEnd($writer)
647         {
648                 $this->renderAllPendingScriptFiles($writer);
649         }
650
651         public function markScriptFileAsRendered($url)
652         {
653                 $this->_renderedScriptFiles[$url] = $url;
654                 $params=func_get_args();
655                 $this->_page->registerCachingAction('Page.ClientScript','markScriptFileAsRendered',$params);
656         }
657
658         protected function renderScriptFiles($writer, Array $scripts)
659         {
660                 foreach($scripts as $script)
661                 {
662                         $writer->write(TJavaScript::renderScriptFile($script));
663                         $this->markScriptFileAsRendered($script);
664                 }
665         }
666
667         protected function getRenderedScriptFiles()
668         {
669                 return $this->_renderedScriptFiles;
670         }
671
672         /**
673          * @param THtmlWriter writer for the rendering purpose
674          */
675         public function renderAllPendingScriptFiles($writer)
676         {
677                 if(!empty($this->_scriptFiles))
678                 {
679                         $addedScripts = array_diff($this->_scriptFiles,$this->getRenderedScriptFiles());
680                         $this->renderScriptFiles($writer,$addedScripts);
681                 }
682         }
683
684         /**
685          * @param THtmlWriter writer for the rendering purpose
686          */
687         public function renderBeginScripts($writer)
688         {
689                 $writer->write(TJavaScript::renderScriptBlocks($this->_beginScripts));
690         }
691
692         /**
693          * @param THtmlWriter writer for the rendering purpose
694          */
695         public function renderEndScripts($writer)
696         {
697                 $writer->write(TJavaScript::renderScriptBlocks($this->_endScripts));
698         }
699
700         public function renderHiddenFieldsBegin($writer)
701         {
702                 $this->renderHiddenFieldsInt($writer,true);
703         }
704
705         public function renderHiddenFieldsEnd($writer)
706         {
707                 $this->renderHiddenFieldsInt($writer,false);
708         }
709
710         /**
711          * Flushes all pending script registrations
712          * @param THtmlWriter writer for the rendering purpose
713          * @param TControl the control forcing the flush (used only in error messages)
714          */
715         public function flushScriptFiles($writer, $control=null)
716         {
717                 if(!$this->_page->getIsCallback())
718                 {
719                         $this->_page->ensureRenderInForm($control);
720                         $this->renderAllPendingScriptFiles($writer);
721                 }
722         }
723
724         /**
725          * @param THtmlWriter writer for the rendering purpose
726          */
727         protected function renderHiddenFieldsInt($writer, $initial)
728         {
729                 if ($initial) $this->_renderedHiddenFields = array();
730                 $str='';
731                 foreach($this->_hiddenFields as $name=>$value)
732                 {
733                         if (in_array($name,$this->_renderedHiddenFields)) continue;
734                         $id=strtr($name,':','_');
735                         if(is_array($value))
736                         {
737                                 foreach($value as $v)
738                                         $str.='<input type="hidden" name="'.$name.'[]" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n";
739                         }
740                         else
741                         {
742                                 $str.='<input type="hidden" name="'.$name.'" id="'.$id.'" value="'.THttpUtility::htmlEncode($value)."\" />\n";
743                         }
744                         $this->_renderedHiddenFields[] = $name;
745                 }
746                 if($str!=='')
747                         $writer->write("<div style=\"visibility:hidden;\">\n".$str."</div>\n");
748         }
749
750         public function getHiddenFields()
751         {
752                 return $this->_hiddenFields;
753         }
754
755         /**
756          * Checks whether page rendering has not begun yet
757          */
758         protected function checkIfNotInRender()
759         {
760                 if ($form = $this->_page->InFormRender)
761                         throw new Exception('Operation invalid when page is already rendering');
762         }
763 }
764
765 /**
766  * TClientSideOptions abstract class.
767  *
768  * TClientSideOptions manages client-side options for components that have
769  * common client-side javascript behaviours and client-side events such as
770  * between ActiveControls and validators.
771  *
772  * @author <weizhuo[at]gmail[dot]com>
773  * @package System.Web.UI
774  * @since 3.0
775  */
776 abstract class TClientSideOptions extends TComponent
777 {
778         /**
779          * @var TMap list of client-side options.
780          */
781         private $_options;
782
783         /**
784          * Adds on client-side event handler by wrapping the code within a
785          * javascript function block. If the code begins with "javascript:", the
786          * code is assumed to be a javascript function block rather than arbiturary
787          * javascript statements.
788          * @param string option name
789          * @param string javascript statements.
790          */
791         protected function setFunction($name, $code)
792         {
793                 if(!TJavaScript::isJsLiteral($code))
794                         $code = TJavaScript::quoteJsLiteral($this->ensureFunction($code));
795                 $this->setOption($name, $code);
796         }
797
798         /**
799          * @return string gets a particular option, null if not set.
800          */
801         protected function getOption($name)
802         {
803                 if ($this->_options)
804                         return $this->_options->itemAt($name);
805                 else
806                         return null;
807         }
808
809         /**
810          * @param string option name
811          * @param mixed option value.
812          */
813         protected function setOption($name, $value)
814         {
815                 $this->getOptions()->add($name, $value);
816         }
817
818         /**
819          * @return TMap gets the list of options as TMap
820          */
821         public function getOptions()
822         {
823                 if (!$this->_options)
824                         $this->_options = Prado::createComponent('System.Collections.TMap');
825                 return $this->_options;
826         }
827
828         /**
829          * Ensure that the javascript statements are wrapped in a javascript
830          * function block as <code>function(sender, parameter){ //code }</code>.
831          */
832         protected function ensureFunction($javascript)
833         {
834                 return "function(sender, parameter){ {$javascript} }";
835         }
836 }
837