我创建了一个类似下面注册自己的脚本一个widget
class MyWidget extends CWidget {
public function run(){
Yii::app()->clientScript->registerScript(__CLASS__, <<<JAVASCRIPT
var a = "Hello World!";
JAVASCRIPT
, CClientScript::POS_END);
}
}
而在布局,我叫这样的小部件
<?php $this->widget('MyWidget');?>
<?php echo $content;?>
但是,在一个视图文件,我需要通过小工具声明的变量。
<?php
Yii::app()->clientScript->registerScript('script', <<<JAVASCRIPT
alert(a);
JAVASCRIPT
, CClientScript::POS_END);
?>
请注意,在这两种方法registerScript我用POS_END作为脚本位置,因为我打算在以后把所有的脚本(包括CoreScript如jQuery的,jQueryUI的等)的<body>
标签。
问题是,所呈现的脚本将显示来自视图文件,之后从插件的一个的一个。
alert(a);
var a = "Hello World!";
正如我们所看到的,上面的代码将无法正常工作,所以我需要把第一线的第二线。
关于如何强制命令任何想法? 我可以接受延长CClientScript
(并创建一个新registerScript
只要法)都将在终端位置呈现的脚本,我没有拉高于行内代码的Javascript到一个新的包或文件。
所以,我终于找到一个黑客做到这一点。 我向一个新的ClientScript
类和修改registerScript
方法,因此将接受另一个PARAM $level
。
public function registerScript($id, $script, $position = self::POS_END, $level = 1);
想想$level
,就像z-index
CSS中,除了数量更大$level
,下脚本的位置会。
例如
Yii::app()->clientScript->registerScript('script1', '/** SCRIPT #1 **/', CClientScript::POS_END, 1);
Yii::app()->clientScript->registerScript('script2', '/** SCRIPT #2 **/', CClientScript::POS_END, 2);
Yii::app()->clientScript->registerScript('script3', '/** SCRIPT #3 **/', CClientScript::POS_END, 1);
即使script3
之后宣布script2
,在渲染的脚本,它会显示上述script2
自$level
的价值script2
大于script3
的。
这里是我的解决方案的代码。 它的工作就像我想要什么,虽然我不知道,如果优化布置方法就够了。
/**
* ClientScript manages Javascript and CSS.
*/
class ClientScript extends CClientScript {
public $scriptLevels = array();
/**
* Registers a piece of javascript code.
* @param string $id ID that uniquely identifies this piece of JavaScript code
* @param string $script the javascript code
* @param integer $position the position of the JavaScript code.
* @param integer $level the rendering priority of the JavaScript code in a position.
* @return CClientScript the CClientScript object itself (to support method chaining, available since version 1.1.5).
*/
public function registerScript($id, $script, $position = self::POS_END, $level = 1) {
$this->scriptLevels[$id] = $level;
return parent::registerScript($id, $script, $position);
}
/**
* Renders the registered scripts.
* Overriding from CClientScript.
* @param string $output the existing output that needs to be inserted with script tags
*/
public function render(&$output) {
if (!$this->hasScripts)
return;
$this->renderCoreScripts();
if (!empty($this->scriptMap))
$this->remapScripts();
$this->unifyScripts();
//===================================
//Arranging the priority
$this->rearrangeLevels();
//===================================
$this->renderHead($output);
if ($this->enableJavaScript) {
$this->renderBodyBegin($output);
$this->renderBodyEnd($output);
}
}
/**
* Rearrange the script levels.
*/
public function rearrangeLevels() {
$scriptLevels = $this->scriptLevels;
foreach ($this->scripts as $position => &$scripts) {
$newscripts = array();
$tempscript = array();
foreach ($scripts as $id => $script) {
$level = isset($scriptLevels[$id]) ? $scriptLevels[$id] : 1;
$tempscript[$level][$id] = $script;
}
foreach ($tempscript as $s) {
foreach ($s as $id => $script) {
$newscripts[$id] = $script;
}
}
$scripts = $newscripts;
}
}
}
所以,我只是需要把类作为clientScript组件的配置
'components' => array(
'clientScript' => array(
'class' => 'ClientScript'
)
)
尝试注册HEAD
Yii::app()->clientScript->registerScript(__CLASS__, <<<JAVASCRIPT
var a = "Hello World!";
JAVASCRIPT
, CClientScript::POS_HEAD);
我已经贡献了一个补丁的Yii允许排序(前置,追加,数量)
你可以在这里找到https://github.com/yiisoft/yii/pull/2263
如果没有得到它的地方变成你,那么你可以扩展到CClientScript自己的类申请我的变化
但总体正确写入JS应的顺序,例如定义的独立工作,而不是一些全球范围内瓦尔你可以指定它们作为属性窗口(访问一个不存在的属性不扔在JS错误)
有没有必要延长CClienScript。 一个简单的解决这个问题是创建在你的控制器中的$脚本阵列控制器和视图脚本添加到该变量。 在您的布局文件你已经注册你想在它之前被渲染的那些后,您会登记存储在$脚本阵列的脚本。 例如:
在您的控制器
public $scripts = [];
在您的布局:
$baseURL = Yii::app()->request->baseUrl;
$clientScript = Yii::app()->clientScript;
$clientScript->registerScriptFile( $baseURL . '/js/jquery.min.js', CClientScript::POS_END );
$clientScript->registerScriptFile( $baseURL . '/js/bootstrap.min.js', CClientScript::POS_END);
在您的视图
<?php array_push($this->scripts,"/js/summernote.min.js");?>
重写CClientScript类作为@Petra说,这里是我使用的代码,使用@Petra代码和我没有制定出之后。
class ClientScript extends CClientScript {
public $scriptLevels;
public function registerScript($id, $script, $position = null, $level = 1, array $htmlOptions = array()) {
$this->scriptLevels[$id] = $level;
return parent::registerScript($id, $script, $position, $htmlOptions);
}
public function render(&$output) {
foreach ($this->scripts as $key => $value) {
$this->scripts[$key] = $this->reorderScripts($value);
}
parent::render($output);
}
public function reorderScripts($element) {
$tempScripts = array();
$buffer = array();
foreach ($element as $key => $value) {
if (isset($this->scriptLevels[$key])) {
$tempScripts[$this->scriptLevels[$key]][$key] = $value;
}
}
ksort($tempScripts);
foreach ($tempScripts as $value) {
foreach ($value as $k => $v) {
$buffer[$k] = $v;
}
}
return $buffer;
}
}
然后,转到您的配置文件,并在组件部分修改如下:
'components' => array(
.
.
'clientScript' => array(
'class' => 'ClientScript'
),
)