I created a widget that registers its own script like below
class MyWidget extends CWidget {
public function run(){
Yii::app()->clientScript->registerScript(__CLASS__, <<<JAVASCRIPT
var a = "Hello World!";
JAVASCRIPT
, CClientScript::POS_END);
}
}
And in the layout, I call the widget like this
<?php $this->widget('MyWidget');?>
<?php echo $content;?>
But in a view file, I need the variable declared by that widget.
<?php
Yii::app()->clientScript->registerScript('script', <<<JAVASCRIPT
alert(a);
JAVASCRIPT
, CClientScript::POS_END);
?>
Note that in both registerScript method I use POS_END as the script position since I intend to put all of the scripts (including the CoreScript e.g. jQuery, jQueryUI etc) after the <body> tag.
The problem is that the rendered script will show the one from the view file and after that the one from the widget.
alert(a);
var a = "Hello World!";
As we can see, the above code won’t work so I need to put the the second line above the first line.
Any idea on how to force the order? I’m okay with extending the CClientScript (and creating a new registerScript method) as long as all of the scripts will be rendered in the end position and I don’t have to pull those inline Javascript codes above to a new package or file.
So I finally find a hack to do this. I extend a new
ClientScriptclass and modify theregisterScriptmethod so it will accept another param$level.Think about
$leveljust likez-indexin CSS, except the greater the number of$levelis, the lower the position of the script will be.For example
Even though
script3is declared afterscript2, in the rendered script, it will show abovescript2since the$levelvalue ofscript2is greater thanscript3‘s.Here’s my solution’s code. It’s working like what I want although I’m not sure if the arranging method is optimized enough.
So I just need to put the class as the clientScript component in the config