CClientScript.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. <?php
  2. /**
  3. * CClientScript class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CClientScript manages JavaScript and CSS stylesheets for views.
  12. *
  13. * @property string $coreScriptUrl The base URL of all core javascript files.
  14. *
  15. * @author Qiang Xue <qiang.xue@gmail.com>
  16. * @package system.web
  17. * @since 1.0
  18. */
  19. class CClientScript extends CApplicationComponent
  20. {
  21. /**
  22. * The script is rendered in the head section right before the title element.
  23. */
  24. const POS_HEAD=0;
  25. /**
  26. * The script is rendered at the beginning of the body section.
  27. */
  28. const POS_BEGIN=1;
  29. /**
  30. * The script is rendered at the end of the body section.
  31. */
  32. const POS_END=2;
  33. /**
  34. * The script is rendered inside window onload function.
  35. */
  36. const POS_LOAD=3;
  37. /**
  38. * The body script is rendered inside a jQuery ready function.
  39. */
  40. const POS_READY=4;
  41. /**
  42. * @var boolean whether JavaScript should be enabled. Defaults to true.
  43. */
  44. public $enableJavaScript=true;
  45. /**
  46. * @var array the mapping between script file names and the corresponding script URLs.
  47. * The array keys are script file names (without directory part) and the array values are the corresponding URLs.
  48. * If an array value is false, the corresponding script file will not be rendered.
  49. * If an array key is '*.js' or '*.css', the corresponding URL will replace all
  50. * JavaScript files or CSS files, respectively.
  51. *
  52. * This property is mainly used to optimize the generated HTML pages
  53. * by merging different scripts files into fewer and optimized script files.
  54. */
  55. public $scriptMap=array();
  56. /**
  57. * @var array list of custom script packages (name=>package spec).
  58. * This property keeps a list of named script packages, each of which can contain
  59. * a set of CSS and/or JavaScript script files, and their dependent package names.
  60. * By calling {@link registerPackage}, one can register a whole package of client
  61. * scripts together with their dependent packages and render them in the HTML output.
  62. *
  63. * The array structure is as follows:
  64. * <pre>
  65. * array(
  66. * 'package-name'=>array(
  67. * 'basePath'=>'alias of the directory containing the script files',
  68. * 'baseUrl'=>'base URL for the script files',
  69. * 'js'=>array(list of js files relative to basePath/baseUrl),
  70. * 'css'=>array(list of css files relative to basePath/baseUrl),
  71. * 'depends'=>array(list of dependent packages),
  72. * ),
  73. * ......
  74. * )
  75. * </pre>
  76. *
  77. * The JS and CSS files listed are relative to 'basePath'.
  78. * For example, if 'basePath' is 'application.assets', a script named 'comments.js'
  79. * will refer to the file 'protected/assets/comments.js'.
  80. *
  81. * When a script is being rendered in HTML, it will be prefixed with 'baseUrl'.
  82. * For example, if 'baseUrl' is '/assets', the 'comments.js' script will be rendered
  83. * using URL '/assets/comments.js'.
  84. *
  85. * If 'baseUrl' does not start with '/', the relative URL of the application entry
  86. * script will be inserted at the beginning. For example, if 'baseUrl' is 'assets'
  87. * and the current application runs with the URL 'http://localhost/demo/index.php',
  88. * then the 'comments.js' script will be rendered using URL '/demo/assets/comments.js'.
  89. *
  90. * If 'baseUrl' is not set, the script will be published by {@link CAssetManager}
  91. * and the corresponding published URL will be used.
  92. *
  93. * When calling {@link registerPackage} to register a script package,
  94. * this property will be checked first followed by {@link corePackages}.
  95. * If a package is found, it will be registered for rendering later on.
  96. *
  97. * @since 1.1.7
  98. */
  99. public $packages=array();
  100. /**
  101. * @var array list of core script packages (name=>package spec).
  102. * Please refer to {@link packages} for details about package spec.
  103. *
  104. * By default, the core script packages are specified in 'framework/web/js/packages.php'.
  105. * You may configure this property to customize the core script packages.
  106. *
  107. * When calling {@link registerPackage} to register a script package,
  108. * {@link packages} will be checked first followed by this property.
  109. * If a package is found, it will be registered for rendering later on.
  110. *
  111. * @since 1.1.7
  112. */
  113. public $corePackages;
  114. /**
  115. * @var array the registered JavaScript code blocks (position, key => code)
  116. */
  117. public $scripts=array();
  118. /**
  119. * @var array the registered CSS files (CSS URL=>media type).
  120. */
  121. protected $cssFiles=array();
  122. /**
  123. * @var array the registered JavaScript files (position, key => URL)
  124. */
  125. protected $scriptFiles=array();
  126. /**
  127. * @var array the registered head meta tags. Each array element represents an option array
  128. * that will be passed as the last parameter of {@link CHtml::metaTag}.
  129. * @since 1.1.3
  130. */
  131. protected $metaTags=array();
  132. /**
  133. * @var array the registered head link tags. Each array element represents an option array
  134. * that will be passed as the last parameter of {@link CHtml::linkTag}.
  135. * @since 1.1.3
  136. */
  137. protected $linkTags=array();
  138. /**
  139. * @var array the registered css code blocks (key => array(CSS code, media type)).
  140. * @since 1.1.3
  141. */
  142. protected $css=array();
  143. /**
  144. * @var boolean whether there are any javascript or css to be rendered.
  145. * @since 1.1.7
  146. */
  147. protected $hasScripts=false;
  148. /**
  149. * @var array the registered script packages (name => package spec)
  150. * @since 1.1.7
  151. */
  152. protected $coreScripts=array();
  153. /**
  154. * @var integer Where the scripts registered using {@link registerCoreScript} or {@link registerPackage}
  155. * will be inserted in the page. This can be one of the CClientScript::POS_* constants.
  156. * Defaults to CClientScript::POS_HEAD.
  157. * @since 1.1.3
  158. */
  159. public $coreScriptPosition=self::POS_HEAD;
  160. /**
  161. * @var integer Where the scripts registered using {@link registerScriptFile} will be inserted in the page.
  162. * This can be one of the CClientScript::POS_* constants.
  163. * Defaults to CClientScript::POS_HEAD.
  164. * @since 1.1.11
  165. */
  166. public $defaultScriptFilePosition=self::POS_HEAD;
  167. /**
  168. * @var integer Where the scripts registered using {@link registerScript} will be inserted in the page.
  169. * This can be one of the CClientScript::POS_* constants.
  170. * Defaults to CClientScript::POS_READY.
  171. * @since 1.1.11
  172. */
  173. public $defaultScriptPosition=self::POS_READY;
  174. private $_baseUrl;
  175. /**
  176. * Cleans all registered scripts.
  177. */
  178. public function reset()
  179. {
  180. $this->hasScripts=false;
  181. $this->coreScripts=array();
  182. $this->cssFiles=array();
  183. $this->css=array();
  184. $this->scriptFiles=array();
  185. $this->scripts=array();
  186. $this->metaTags=array();
  187. $this->linkTags=array();
  188. $this->recordCachingAction('clientScript','reset',array());
  189. }
  190. /**
  191. * Renders the registered scripts.
  192. * This method is called in {@link CController::render} when it finishes
  193. * rendering content. CClientScript thus gets a chance to insert script tags
  194. * at <code>head</code> and <code>body</code> sections in the HTML output.
  195. * @param string $output the existing output that needs to be inserted with script tags
  196. */
  197. public function render(&$output)
  198. {
  199. if(!$this->hasScripts)
  200. return;
  201. $this->renderCoreScripts();
  202. if(!empty($this->scriptMap))
  203. $this->remapScripts();
  204. $this->unifyScripts();
  205. $this->renderHead($output);
  206. if($this->enableJavaScript)
  207. {
  208. $this->renderBodyBegin($output);
  209. $this->renderBodyEnd($output);
  210. }
  211. }
  212. /**
  213. * Removes duplicated scripts from {@link scriptFiles}.
  214. * @since 1.1.5
  215. */
  216. protected function unifyScripts()
  217. {
  218. if(!$this->enableJavaScript)
  219. return;
  220. $map=array();
  221. if(isset($this->scriptFiles[self::POS_HEAD]))
  222. $map=$this->scriptFiles[self::POS_HEAD];
  223. if(isset($this->scriptFiles[self::POS_BEGIN]))
  224. {
  225. foreach($this->scriptFiles[self::POS_BEGIN] as $scriptFile=>$scriptFileValue)
  226. {
  227. if(isset($map[$scriptFile]))
  228. unset($this->scriptFiles[self::POS_BEGIN][$scriptFile]);
  229. else
  230. $map[$scriptFile]=true;
  231. }
  232. }
  233. if(isset($this->scriptFiles[self::POS_END]))
  234. {
  235. foreach($this->scriptFiles[self::POS_END] as $key=>$scriptFile)
  236. {
  237. if(isset($map[$key]))
  238. unset($this->scriptFiles[self::POS_END][$key]);
  239. }
  240. }
  241. }
  242. /**
  243. * Uses {@link scriptMap} to re-map the registered scripts.
  244. */
  245. protected function remapScripts()
  246. {
  247. $cssFiles=array();
  248. foreach($this->cssFiles as $url=>$media)
  249. {
  250. $name=basename($url);
  251. if(isset($this->scriptMap[$name]))
  252. {
  253. if($this->scriptMap[$name]!==false)
  254. $cssFiles[$this->scriptMap[$name]]=$media;
  255. }
  256. elseif(isset($this->scriptMap['*.css']))
  257. {
  258. if($this->scriptMap['*.css']!==false)
  259. $cssFiles[$this->scriptMap['*.css']]=$media;
  260. }
  261. else
  262. $cssFiles[$url]=$media;
  263. }
  264. $this->cssFiles=$cssFiles;
  265. $jsFiles=array();
  266. foreach($this->scriptFiles as $position=>$scriptFiles)
  267. {
  268. $jsFiles[$position]=array();
  269. foreach($scriptFiles as $scriptFile=>$scriptFileValue)
  270. {
  271. $name=basename($scriptFile);
  272. if(isset($this->scriptMap[$name]))
  273. {
  274. if($this->scriptMap[$name]!==false)
  275. $jsFiles[$position][$this->scriptMap[$name]]=$this->scriptMap[$name];
  276. }
  277. elseif(isset($this->scriptMap['*.js']))
  278. {
  279. if($this->scriptMap['*.js']!==false)
  280. $jsFiles[$position][$this->scriptMap['*.js']]=$this->scriptMap['*.js'];
  281. }
  282. else
  283. $jsFiles[$position][$scriptFile]=$scriptFileValue;
  284. }
  285. }
  286. $this->scriptFiles=$jsFiles;
  287. }
  288. /**
  289. * Composes script HTML block from the given script values,
  290. * attempting to group scripts at single 'script' tag if possible.
  291. * @param array $scripts script values to process.
  292. * @return string HTML output
  293. */
  294. protected function renderScriptBatch(array $scripts)
  295. {
  296. $html = '';
  297. $scriptBatches = array();
  298. foreach($scripts as $scriptValue)
  299. {
  300. if(is_array($scriptValue))
  301. {
  302. $scriptContent = $scriptValue['content'];
  303. unset($scriptValue['content']);
  304. $scriptHtmlOptions = $scriptValue;
  305. ksort($scriptHtmlOptions);
  306. }
  307. else
  308. {
  309. $scriptContent = $scriptValue;
  310. $scriptHtmlOptions = array();
  311. }
  312. $key=serialize($scriptHtmlOptions);
  313. $scriptBatches[$key]['htmlOptions']=$scriptHtmlOptions;
  314. $scriptBatches[$key]['scripts'][]=$scriptContent;
  315. }
  316. foreach($scriptBatches as $scriptBatch)
  317. if(!empty($scriptBatch['scripts']))
  318. $html.=CHtml::script(implode("\n",$scriptBatch['scripts']),$scriptBatch['htmlOptions'])."\n";
  319. return $html;
  320. }
  321. /**
  322. * Renders the specified core javascript library.
  323. */
  324. public function renderCoreScripts()
  325. {
  326. if($this->coreScripts===null)
  327. return;
  328. $cssFiles=array();
  329. $jsFiles=array();
  330. foreach($this->coreScripts as $name=>$package)
  331. {
  332. $baseUrl=$this->getPackageBaseUrl($name);
  333. if(!empty($package['js']))
  334. {
  335. foreach($package['js'] as $js)
  336. $jsFiles[$baseUrl.'/'.$js]=$baseUrl.'/'.$js;
  337. }
  338. if(!empty($package['css']))
  339. {
  340. foreach($package['css'] as $css)
  341. $cssFiles[$baseUrl.'/'.$css]='';
  342. }
  343. }
  344. // merge in place
  345. if($cssFiles!==array())
  346. {
  347. foreach($this->cssFiles as $cssFile=>$media)
  348. $cssFiles[$cssFile]=$media;
  349. $this->cssFiles=$cssFiles;
  350. }
  351. if($jsFiles!==array())
  352. {
  353. if(isset($this->scriptFiles[$this->coreScriptPosition]))
  354. {
  355. foreach($this->scriptFiles[$this->coreScriptPosition] as $url => $value)
  356. $jsFiles[$url]=$value;
  357. }
  358. $this->scriptFiles[$this->coreScriptPosition]=$jsFiles;
  359. }
  360. }
  361. /**
  362. * Inserts the scripts in the head section.
  363. * @param string $output the output to be inserted with scripts.
  364. */
  365. public function renderHead(&$output)
  366. {
  367. $html='';
  368. foreach($this->metaTags as $meta)
  369. $html.=CHtml::metaTag($meta['content'],null,null,$meta)."\n";
  370. foreach($this->linkTags as $link)
  371. $html.=CHtml::linkTag(null,null,null,null,$link)."\n";
  372. foreach($this->cssFiles as $url=>$media)
  373. $html.=CHtml::cssFile($url,$media)."\n";
  374. foreach($this->css as $css)
  375. $html.=CHtml::css($css[0],$css[1])."\n";
  376. if($this->enableJavaScript)
  377. {
  378. if(isset($this->scriptFiles[self::POS_HEAD]))
  379. {
  380. foreach($this->scriptFiles[self::POS_HEAD] as $scriptFileValueUrl=>$scriptFileValue)
  381. {
  382. if(is_array($scriptFileValue))
  383. $html.=CHtml::scriptFile($scriptFileValueUrl,$scriptFileValue)."\n";
  384. else
  385. $html.=CHtml::scriptFile($scriptFileValueUrl)."\n";
  386. }
  387. }
  388. if(isset($this->scripts[self::POS_HEAD]))
  389. $html.=$this->renderScriptBatch($this->scripts[self::POS_HEAD]);
  390. }
  391. if($html!=='')
  392. {
  393. $count=0;
  394. $output=preg_replace('/(<title\b[^>]*>|<\\/head\s*>)/is','<###head###>$1',$output,1,$count);
  395. if($count)
  396. $output=str_replace('<###head###>',$html,$output);
  397. else
  398. $output=$html.$output;
  399. }
  400. }
  401. /**
  402. * Inserts the scripts at the beginning of the body section.
  403. * @param string $output the output to be inserted with scripts.
  404. */
  405. public function renderBodyBegin(&$output)
  406. {
  407. $html='';
  408. if(isset($this->scriptFiles[self::POS_BEGIN]))
  409. {
  410. foreach($this->scriptFiles[self::POS_BEGIN] as $scriptFileUrl=>$scriptFileValue)
  411. {
  412. if(is_array($scriptFileValue))
  413. $html.=CHtml::scriptFile($scriptFileUrl,$scriptFileValue)."\n";
  414. else
  415. $html.=CHtml::scriptFile($scriptFileUrl)."\n";
  416. }
  417. }
  418. if(isset($this->scripts[self::POS_BEGIN]))
  419. $html.=$this->renderScriptBatch($this->scripts[self::POS_BEGIN]);
  420. if($html!=='')
  421. {
  422. $count=0;
  423. $output=preg_replace('/(<body\b[^>]*>)/is','$1<###begin###>',$output,1,$count);
  424. if($count)
  425. $output=str_replace('<###begin###>',$html,$output);
  426. else
  427. $output=$html.$output;
  428. }
  429. }
  430. /**
  431. * Inserts the scripts at the end of the body section.
  432. * @param string $output the output to be inserted with scripts.
  433. */
  434. public function renderBodyEnd(&$output)
  435. {
  436. if(!isset($this->scriptFiles[self::POS_END]) && !isset($this->scripts[self::POS_END])
  437. && !isset($this->scripts[self::POS_READY]) && !isset($this->scripts[self::POS_LOAD]))
  438. return;
  439. $fullPage=0;
  440. $output=preg_replace('/(<\\/body\s*>)/is','<###end###>$1',$output,1,$fullPage);
  441. $html='';
  442. if(isset($this->scriptFiles[self::POS_END]))
  443. {
  444. foreach($this->scriptFiles[self::POS_END] as $scriptFileUrl=>$scriptFileValue)
  445. {
  446. if(is_array($scriptFileValue))
  447. $html.=CHtml::scriptFile($scriptFileUrl,$scriptFileValue)."\n";
  448. else
  449. $html.=CHtml::scriptFile($scriptFileUrl)."\n";
  450. }
  451. }
  452. $scripts=isset($this->scripts[self::POS_END]) ? $this->scripts[self::POS_END] : array();
  453. if(isset($this->scripts[self::POS_READY]))
  454. {
  455. if($fullPage)
  456. $scripts[]="jQuery(function($) {\n".implode("\n",$this->scripts[self::POS_READY])."\n});";
  457. else
  458. $scripts[]=implode("\n",$this->scripts[self::POS_READY]);
  459. }
  460. if(isset($this->scripts[self::POS_LOAD]))
  461. {
  462. if($fullPage)
  463. $scripts[]="jQuery(window).on('load',function() {\n".implode("\n",$this->scripts[self::POS_LOAD])."\n});";
  464. else
  465. $scripts[]=implode("\n",$this->scripts[self::POS_LOAD]);
  466. }
  467. if(!empty($scripts))
  468. $html.=$this->renderScriptBatch($scripts);
  469. if($fullPage)
  470. $output=str_replace('<###end###>',$html,$output);
  471. else
  472. $output=$output.$html;
  473. }
  474. /**
  475. * Returns the base URL of all core javascript files.
  476. * If the base URL is not explicitly set, this method will publish the whole directory
  477. * 'framework/web/js/source' and return the corresponding URL.
  478. * @return string the base URL of all core javascript files
  479. */
  480. public function getCoreScriptUrl()
  481. {
  482. if($this->_baseUrl!==null)
  483. return $this->_baseUrl;
  484. else
  485. return $this->_baseUrl=Yii::app()->getAssetManager()->publish(YII_PATH.'/web/js/source');
  486. }
  487. /**
  488. * Sets the base URL of all core javascript files.
  489. * This setter is provided in case when core javascript files are manually published
  490. * to a pre-specified location. This may save asset publishing time for large-scale applications.
  491. * @param string $value the base URL of all core javascript files.
  492. */
  493. public function setCoreScriptUrl($value)
  494. {
  495. $this->_baseUrl=$value;
  496. }
  497. /**
  498. * Returns the base URL for a registered package with the specified name.
  499. * If needed, this method may publish the assets of the package and returns the published base URL.
  500. * @param string $name the package name
  501. * @return string the base URL for the named package. False is returned if the package is not registered yet.
  502. * @see registerPackage
  503. * @since 1.1.8
  504. */
  505. public function getPackageBaseUrl($name)
  506. {
  507. if(!isset($this->coreScripts[$name]))
  508. return false;
  509. $package=$this->coreScripts[$name];
  510. if(isset($package['baseUrl']))
  511. {
  512. $baseUrl=$package['baseUrl'];
  513. if($baseUrl==='' || $baseUrl[0]!=='/' && strpos($baseUrl,'://')===false)
  514. $baseUrl=Yii::app()->getRequest()->getBaseUrl().'/'.$baseUrl;
  515. $baseUrl=rtrim($baseUrl,'/');
  516. }
  517. elseif(isset($package['basePath']))
  518. $baseUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias($package['basePath']));
  519. else
  520. $baseUrl=$this->getCoreScriptUrl();
  521. return $this->coreScripts[$name]['baseUrl']=$baseUrl;
  522. }
  523. /**
  524. * Registers a script package that is listed in {@link packages}.
  525. * This method is the same as {@link registerCoreScript}.
  526. * @param string $name the name of the script package.
  527. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  528. * @since 1.1.7
  529. * @see renderCoreScript
  530. */
  531. public function registerPackage($name)
  532. {
  533. return $this->registerCoreScript($name);
  534. }
  535. /**
  536. * Registers a script package that is listed in {@link packages}.
  537. * @param string $name the name of the script package.
  538. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  539. * @see renderCoreScript
  540. */
  541. public function registerCoreScript($name)
  542. {
  543. if(isset($this->coreScripts[$name]))
  544. return $this;
  545. if(isset($this->packages[$name]))
  546. $package=$this->packages[$name];
  547. else
  548. {
  549. if($this->corePackages===null)
  550. $this->corePackages=require(YII_PATH.'/web/js/packages.php');
  551. if(isset($this->corePackages[$name]))
  552. $package=$this->corePackages[$name];
  553. }
  554. if(isset($package))
  555. {
  556. if(!empty($package['depends']))
  557. {
  558. foreach($package['depends'] as $p)
  559. $this->registerCoreScript($p);
  560. }
  561. $this->coreScripts[$name]=$package;
  562. $this->hasScripts=true;
  563. $params=func_get_args();
  564. $this->recordCachingAction('clientScript','registerCoreScript',$params);
  565. }
  566. elseif(YII_DEBUG)
  567. throw new CException('There is no CClientScript package: '.$name);
  568. else
  569. Yii::log('There is no CClientScript package: '.$name,CLogger::LEVEL_WARNING,'system.web.CClientScript');
  570. return $this;
  571. }
  572. /**
  573. * Registers a CSS file
  574. * @param string $url URL of the CSS file
  575. * @param string $media media that the CSS file should be applied to. If empty, it means all media types.
  576. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  577. */
  578. public function registerCssFile($url,$media='')
  579. {
  580. $this->hasScripts=true;
  581. $this->cssFiles[$url]=$media;
  582. $params=func_get_args();
  583. $this->recordCachingAction('clientScript','registerCssFile',$params);
  584. return $this;
  585. }
  586. /**
  587. * Registers a piece of CSS code.
  588. * @param string $id ID that uniquely identifies this piece of CSS code
  589. * @param string $css the CSS code
  590. * @param string $media media that the CSS code should be applied to. If empty, it means all media types.
  591. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  592. */
  593. public function registerCss($id,$css,$media='')
  594. {
  595. $this->hasScripts=true;
  596. $this->css[$id]=array($css,$media);
  597. $params=func_get_args();
  598. $this->recordCachingAction('clientScript','registerCss',$params);
  599. return $this;
  600. }
  601. /**
  602. * Registers a javascript file.
  603. * @param string $url URL of the javascript file
  604. * @param integer $position the position of the JavaScript code. Valid values include the following:
  605. * <ul>
  606. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  607. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  608. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  609. * </ul>
  610. * @param array $htmlOptions additional HTML attributes
  611. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  612. */
  613. public function registerScriptFile($url,$position=null,array $htmlOptions=array())
  614. {
  615. if($position===null)
  616. $position=$this->defaultScriptFilePosition;
  617. $this->hasScripts=true;
  618. if(empty($htmlOptions))
  619. $value=$url;
  620. else
  621. {
  622. $value=$htmlOptions;
  623. $value['src']=$url;
  624. }
  625. $this->scriptFiles[$position][$url]=$value;
  626. $params=func_get_args();
  627. $this->recordCachingAction('clientScript','registerScriptFile',$params);
  628. return $this;
  629. }
  630. /**
  631. * Registers a piece of javascript code.
  632. * @param string $id ID that uniquely identifies this piece of JavaScript code
  633. * @param string $script the javascript code
  634. * @param integer $position the position of the JavaScript code. Valid values include the following:
  635. * <ul>
  636. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  637. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  638. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  639. * <li>CClientScript::POS_LOAD : the script is inserted in the window.onload() function.</li>
  640. * <li>CClientScript::POS_READY : the script is inserted in the jQuery's ready function.</li>
  641. * </ul>
  642. * @param array $htmlOptions additional HTML attributes
  643. * Note: HTML attributes are not allowed for script positions "CClientScript::POS_LOAD" and "CClientScript::POS_READY".
  644. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  645. */
  646. public function registerScript($id,$script,$position=null,array $htmlOptions=array())
  647. {
  648. if($position===null)
  649. $position=$this->defaultScriptPosition;
  650. $this->hasScripts=true;
  651. if(empty($htmlOptions))
  652. $scriptValue=$script;
  653. else
  654. {
  655. if($position==self::POS_LOAD || $position==self::POS_READY)
  656. throw new CException(Yii::t('yii','Script HTML options are not allowed for "CClientScript::POS_LOAD" and "CClientScript::POS_READY".'));
  657. $scriptValue=$htmlOptions;
  658. $scriptValue['content']=$script;
  659. }
  660. $this->scripts[$position][$id]=$scriptValue;
  661. if($position===self::POS_READY || $position===self::POS_LOAD)
  662. $this->registerCoreScript('jquery');
  663. $params=func_get_args();
  664. $this->recordCachingAction('clientScript','registerScript',$params);
  665. return $this;
  666. }
  667. /**
  668. * Registers a meta tag that will be inserted in the head section (right before the title element) of the resulting page.
  669. *
  670. * <b>Note:</b>
  671. * Each call of this method will cause a rendering of new meta tag, even if their attributes are equal.
  672. *
  673. * <b>Example:</b>
  674. * <pre>
  675. * $cs->registerMetaTag('example', 'description', null, array('lang' => 'en'));
  676. * $cs->registerMetaTag('beispiel', 'description', null, array('lang' => 'de'));
  677. * </pre>
  678. * @param string $content content attribute of the meta tag
  679. * @param string $name name attribute of the meta tag. If null, the attribute will not be generated
  680. * @param string $httpEquiv http-equiv attribute of the meta tag. If null, the attribute will not be generated
  681. * @param array $options other options in name-value pairs (e.g. 'scheme', 'lang')
  682. * @param string $id Optional id of the meta tag to avoid duplicates
  683. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  684. */
  685. public function registerMetaTag($content,$name=null,$httpEquiv=null,$options=array(),$id=null)
  686. {
  687. $this->hasScripts=true;
  688. if($name!==null)
  689. $options['name']=$name;
  690. if($httpEquiv!==null)
  691. $options['http-equiv']=$httpEquiv;
  692. $options['content']=$content;
  693. $this->metaTags[null===$id?count($this->metaTags):$id]=$options;
  694. $params=func_get_args();
  695. $this->recordCachingAction('clientScript','registerMetaTag',$params);
  696. return $this;
  697. }
  698. /**
  699. * Registers a link tag that will be inserted in the head section (right before the title element) of the resulting page.
  700. * @param string $relation rel attribute of the link tag. If null, the attribute will not be generated.
  701. * @param string $type type attribute of the link tag. If null, the attribute will not be generated.
  702. * @param string $href href attribute of the link tag. If null, the attribute will not be generated.
  703. * @param string $media media attribute of the link tag. If null, the attribute will not be generated.
  704. * @param array $options other options in name-value pairs
  705. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.5).
  706. */
  707. public function registerLinkTag($relation=null,$type=null,$href=null,$media=null,$options=array())
  708. {
  709. $this->hasScripts=true;
  710. if($relation!==null)
  711. $options['rel']=$relation;
  712. if($type!==null)
  713. $options['type']=$type;
  714. if($href!==null)
  715. $options['href']=$href;
  716. if($media!==null)
  717. $options['media']=$media;
  718. $this->linkTags[serialize($options)]=$options;
  719. $params=func_get_args();
  720. $this->recordCachingAction('clientScript','registerLinkTag',$params);
  721. return $this;
  722. }
  723. /**
  724. * Checks whether the CSS file has been registered.
  725. * @param string $url URL of the CSS file
  726. * @return boolean whether the CSS file is already registered
  727. */
  728. public function isCssFileRegistered($url)
  729. {
  730. return isset($this->cssFiles[$url]);
  731. }
  732. /**
  733. * Checks whether the CSS code has been registered.
  734. * @param string $id ID that uniquely identifies the CSS code
  735. * @return boolean whether the CSS code is already registered
  736. */
  737. public function isCssRegistered($id)
  738. {
  739. return isset($this->css[$id]);
  740. }
  741. /**
  742. * Checks whether the JavaScript file has been registered.
  743. * @param string $url URL of the javascript file
  744. * @param integer $position the position of the JavaScript code. Valid values include the following:
  745. * <ul>
  746. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  747. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  748. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  749. * </ul>
  750. * @return boolean whether the javascript file is already registered
  751. */
  752. public function isScriptFileRegistered($url,$position=self::POS_HEAD)
  753. {
  754. return isset($this->scriptFiles[$position][$url]);
  755. }
  756. /**
  757. * Checks whether the JavaScript code has been registered.
  758. * @param string $id ID that uniquely identifies the JavaScript code
  759. * @param integer $position the position of the JavaScript code. Valid values include the following:
  760. * <ul>
  761. * <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
  762. * <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
  763. * <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
  764. * <li>CClientScript::POS_LOAD : the script is inserted in the window.onload() function.</li>
  765. * <li>CClientScript::POS_READY : the script is inserted in the jQuery's ready function.</li>
  766. * </ul>
  767. * @return boolean whether the javascript code is already registered
  768. */
  769. public function isScriptRegistered($id,$position=self::POS_READY)
  770. {
  771. return isset($this->scripts[$position][$id]);
  772. }
  773. /**
  774. * Records a method call when an output cache is in effect.
  775. * This is a shortcut to Yii::app()->controller->recordCachingAction.
  776. * In case when controller is absent, nothing is recorded.
  777. * @param string $context a property name of the controller. It refers to an object
  778. * whose method is being called. If empty it means the controller itself.
  779. * @param string $method the method name
  780. * @param array $params parameters passed to the method
  781. * @see COutputCache
  782. */
  783. protected function recordCachingAction($context,$method,$params)
  784. {
  785. if(($controller=Yii::app()->getController())!==null)
  786. $controller->recordCachingAction($context,$method,$params);
  787. }
  788. /**
  789. * Adds a package to packages list.
  790. *
  791. * @param string $name the name of the script package.
  792. * @param array $definition the definition array of the script package,
  793. * @see CClientScript::packages.
  794. * @return static the CClientScript object itself (to support method chaining, available since version 1.1.10).
  795. *
  796. * @since 1.1.9
  797. */
  798. public function addPackage($name,$definition)
  799. {
  800. $this->packages[$name]=$definition;
  801. return $this;
  802. }
  803. }