将特定于页面的Javascript添加到CakePHP中的每个视图

时间:2009-09-15 04:11:14

标签: javascript cakephp

为了保持我的脚本可维护,我将把每个脚本移动到他们自己的文件中,由控制器和操作组织:

// scripts which only apply to /views/posts/add.ctp
/app/webroot/js/page/posts/add.js

// scripts which only apply to /view/users/index.ctp
/app/webroot/js/page/users/index.js

这一切都很酷,但是我希望控制器自动添加这些,因为它显然知道控制器和动作的名称。

我觉得最好的地方是AppController::beforeRender()。 (是?)

唯一的问题是我不知道如何将其实际添加到$scripts_for_layout变量中。我认为获得对javascript辅助对象的引用会起作用,但我无法从控制器中找到它!

class AppController extends Controller {
    var $helpers = array("javascript", "html", "form");

    function beforeRender() {
        // ???
    }
}

9 个答案:

答案 0 :(得分:28)

default.ctp布局文件中很容易做到:

每个控制器和/或控制器/操作自动包含.css个文件的示例(因为我有这个文件,很容易适应.js个文件):

<head>
...
<?php
    if (is_file(WWW_ROOT . 'css' . DS . $this->params['controller'] . '.css')) {
        echo $html->css($this->params['controller']);
    }
    if (is_file(WWW_ROOT . 'css' . DS . $this->params['controller'] . DS . $this->params['action'] . '.css')) {
        echo $html->css($this->params['controller'] . '/' . $this->params['action']);
    }
?>
...
</head>

答案 1 :(得分:15)

就像deceze所说,我们使用布局来做,虽然我发现我们的解决方案更优雅:)

在default.ctp中:

if(isset($cssIncludes)){
    foreach($cssIncludes as $css){
        echo $html->css($css);
    }
}

if(isset($jsIncludes)){
    foreach($jsIncludes as $js){
        echo $javascript->link($js);
    }
}

然后,在我们的控制器动作中,我们定义了这些数组:

$this->set('cssIncludes',array('special')); // this will link to /css/special.css
$this->set('jsIncludes',array('jquery'));   // this will link to /js/jquery.js

对于需要在每个视图中加载的文件,我们只需将“静态”添加相同类型的链接到布局顶部,例如:

echo $javascript->link('global');
echo $html->css('global');

这对我们来说非常有效。祝你好运!

答案 2 :(得分:2)

有点新手,但在阅读之后,我的布局添加了以下内容:

if ($handle = opendir(WWW_ROOT . 'js' . DS . $this->params['controller'] . DS . $this->params['action'])) 
{
    while (false !== ($entry = readdir($handle)))
        {
           $entry = str_replace(".js", "", $entry);
           echo $this->Html->script($entry);

    }
    closedir($handle);
}

答案 3 :(得分:2)

我只需要进行特定于页面的包含,但我在documentation找到了一种更简洁的方法。您可以将其加载到default.ctp中的某个脚本块中。在相应的视图中,只需使用HTML帮助程序来推送脚本:

  

您可以使用块将脚本标记附加到特定块   选项:

echo $this->Html->script('wysiwyg', array('block' => 'scriptBottom'));

<script type="text/javascript" href="/js/wysiwyg.js"></script>添加到块中。

  

在您的布局中,您可以输出添加到的所有脚本标签   “scriptBottom”:

echo $this->fetch('scriptBottom');

答案 4 :(得分:1)

我能想到的最好方法是创建自己的custom AppView并让所有控制器都使用它:

class myController extends AppController {
  var view = 'AppView';
  ...
}

然后,在AppView的某个地方,您需要执行以下操作:

function __construct(&$controller, $register){
  parent::__construct($controller,$register);
  $this->addScript('<script type="text/javascript" src="/path/to/js/' . $this->controller . '/' . $this->action . '.js"></script>');
}

但我先退一步思考一些事情,首先。

平均来说,你的脚本有多大?外部脚本调用的开销(在客户端缓存脚本之前)是否比向主输出流添加几百个字节更好(只需将脚本粘贴到页面中,内联)?

也许你会在中间的某个地方做得更好 - 通过控制器分割你的脚本,但不是动作。这样,在第一次访问任何操作后,客户端都拥有所有操作的所有脚本。这样,您可以避免为所有应用程序的脚本进行大量初始下载,但是您可以避免添加N个http往返(其中N是全新用户访问的操作数)。

解决问题的另一种方法是在javascript中完成所有操作。只是想出一个懒惰的加载方案。因此,您的应用程序只会加载一个非常小的loader.js,并且该脚本会确定要引入的其他JavaScript源。

注意:我从未测试过我的扩展视图黑客,但我敢打赌,如果你真的想这样做,它会起作用。

答案 5 :(得分:0)

Convention over Configuration – what's the big deal?上有一个关于CakePHP博客文章的细节 - 它使用帮助器来指定Javascript文件:

<?php

class JsManagerHelper extends AppHelper {

    var $helpers = array('Javascript');

    //where's our jQuery path relevant to CakePHP's JS dir?
    var $_jqueryPath = 'jquery';

    //where do we keep our page/view relevant scripts?
    var $_pageScriptPath = 'page_specific';

    function myJs() {
    return $this->Javascript->link($this->_jqueryPath . '/' .
                                    $this->_pageScriptPath .'/' .
                                    $this->params['controller'] . '_' .
                                    $this->params['action'], false);
    }

}

?>

然后你在视图中只有$jsManager->myJs();

答案 6 :(得分:0)

我为这个问题撰写了一个插件。

如果您有两个文件:

  • /app/View/Post/add.ctp
  • /app/View/Post/add.js

它会将add.js包含在页面的脚本块中。

  • 应用程序/视图/后/ add.js
  • 应用程序/根目录/ JS /后/ add.js

它会将/js/post/add.js包含在页面的脚本块中。

有一些可爱的功能,它就像豆子一样简单。您甚至可以在.js文件中使用PHP,并使用您在操作中设置的viewVars。最重要的是,您无需破解视图或布局文件即可使其工作,只需在布局中获取“脚本”块即可。您也可以简单地将.js写入另一个视图块。

您可以在此处查看:https://github.com/dizyart/cakephp-viewautoload

它处于早期阶段,所以请务必发表评论和心愿单!

答案 7 :(得分:0)

LI在 W1ckd 片段上工作了一点点(非常少),并且更容易为不同的操作共享相同的js:

if ( is_dir(WWW_ROOT . 'js' . DS . $this->params['controller'] ) && ( $handle = opendir( WWW_ROOT . 'js' . DS . $this->params['controller'] ) ) )
{
    while ( false !== ( $entry = readdir( $handle ) ) )
    {
        if ( in_array( $this->params['action'], explode( '.', $entry ) ) ) {
            $entry = str_replace( ".js", "", $entry );
            echo $this->Html->script( $this->params['controller'].DS.$entry );
        }

    }
    closedir( $handle );
}

这样你就可以拥有:

根目录/ JS /的控制器 / view.edit.add.js

这个js将包含在这三个动作中(查看,编辑,添加)。

答案 8 :(得分:0)

使用Cake v3,你可以这样做。在特定控制器中添加所需的脚本。

//YourController.php
public function beforeRender (Event $event)
{
    array_push($this->scripts, 'Admin/gallery');
    parent::beforeRender($event);
}

在intialize中设置默认值并渲染一次     //AppController.php     public function initialize()     {         父::初始化();

    $this->scripts = [];
}

public function beforeRender (Event $event)
{
    /* Define scripts in beforeRender of Child */
    $this->set('scripts', $this->scripts);
    /*-----------------------------------------*/
}

现在你可以运行一次这个功能了。

<?= $this->Html->script($scripts) ?>