2009-09-15 19 views
12

Nel tentativo di tenere i miei script mantenibile, ho intenzione di spostare ogni nelle loro file, organizzata dal regolatore e l'azione:L'aggiunta di specifiche pagine Javascript per ogni vista in 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 

Questo è tutto fresco , tuttavia, vorrei che questi vengano aggiunti automaticamente dal Controller, poiché ovviamente conosce il nome sia del controller che dell'azione.

Immagino che il posto migliore per questo sia in AppController::beforeRender(). (sì?)

L'unico problema è che non so come aggiungerlo effettivamente alla variabile $scripts_for_layout. Ho pensato che ottenere un riferimento all'oggetto helper funzionasse, ma non riesco a trovarlo dal controller!

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

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

risposta

1

Il modo migliore che posso pensare è quello di creare il proprio custom AppView e hanno tutti i controller usano che:

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

Poi, da qualche parte nel vostro APPVIEW, che ci si vuole fare qualcosa di simile :

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

Ma farei un passo indietro e riflettere su alcune cose, in primo luogo.

Quanto sono grandi i copioni, in media? Il sovraccarico di una chiamata di script esterna (prima che lo script venga memorizzato nella cache dal client) è migliore rispetto all'aggiunta di alcune centinaia di byte al flusso di output principale (semplicemente attaccando lo script alla pagina, inline)?

Forse starai meglio da qualche parte nel mezzo: suddividi gli script in base al controller, ma non all'azione. In questo modo, dopo la prima visita a qualsiasi azione, il client ha tutti gli script per tutte le azioni. In questo modo, si evita un grande download iniziale per tutti gli script dell'applicazione, ma si evita di aggiungere N round-trips HTTP (dove N è il numero di azioni che un nuovo utente visita).

Un altro modo per affrontare il problema è quello di fare tutto in javascript. Basta immaginare uno schema di caricamento lento. Quindi la tua app carica solo un piccolo loader.js, e lo script calcola quali altre sorgenti javascript inserire.

Nota: non ho mai testato il mio hack estendere il punto di vista, ma scommetto che sarà lavoro se vuoi davvero farlo.

28

Molto facile da fare nel file default.ctp di layout:

Un esempio per includere automaticamente .css file per controller e/o il controller/azione (perché avevo questo giro, facilmente adattabile a .js file):

<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> 
+3

+1 per approccio pulito e comprensione. 'APP.WEBROOT_DIR.DS' può essere sostituito con la costante' WWW_ROOT'. – deizel

+0

Un buon punto, dovrebbe essere meno incline agli errori quando si modifica anche la struttura della directory. Lo ha cambiato :) – deceze

+1

deceze ... sul serio ... sei come l'unico guru della torta in SO, lo giuro. Nelle ultime 3 settimane devo averti dato 400 replicati. :) – nickf

15

Come deceze sta dicendo, lo facciamo utilizzando il layout, anche se trovo la nostra soluzione un po 'più elegante :)

in default.CTP:

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

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

Poi, nelle nostre azioni di controllo, definiamo queste matrici:

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

Per i file che devono essere caricati in ogni vista, abbiamo semplicemente aggiungere lo stesso tipo di collegamento "staticamente" all'inizio del layout, ad esempio:

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

Questo funziona davvero bene per noi. In bocca al lupo!

+0

Grazie per questo stavo cercando un modo per definire gli script nel controller. Sebbene io non chiami il codice php in .ctp elegante. Ci deve essere un modo più pulito. – dewwwald

2

Kinda nuovo a questo, ma dopo aver letto questo aggiunto il testo seguente mio layout:

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); 
} 
+0

Spiega un po 'di più cosa fa questo codice. – cereallarceny

+0

Snippet molto bello! L'unica cosa negativa è che non puoi usare lo stesso js in due controller/azioni diversi ... –

0

C'è una dadi e bulloni di CakePHP blog post sul Convention over Configuration – what's the big deal? - che utilizza un assistente per la specifica file 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); 
    } 

} 

?> 

E quindi hai solo $jsManager->myJs(); nella tua vista.

2

Ho appena dovuto fare l'inclusione specifica della pagina, ma ho trovato un modo più ordinato per farlo nello documentation. Si può semplicemente caricarlo in qualche blocco di script nel file default.ctp. E in vista corrispondente basta usare helper HTML per spingere uno script:

È possibile aggiungere il tag script per un blocco specifico utilizzando il blocco opzione:

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

che aggiunge <script type="text/javascript" href="/js/wysiwyg.js"></script> ad un blocco .

Nel vostro layout è possibile uscita di tutti i tag di script aggiunto alla ‘scriptBottom’:

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

ho scritto un plugin per questo problema esatto.

Se si dispone di due file:

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

includerà il add.js nel blocco di script della pagina.

O

  • app/Vista/Post/add.js
  • app/Webroot/js/Post/add.js

si include/js/post/add.js nel blocco di script della pagina.

Alcune caratteristiche carine sono lì ed è semplice come fagioli.Puoi persino usare PHP nei tuoi file .js e usare viewVars che hai impostato nell'azione. Soprattutto, non è necessario modificare la vista o i file di layout per farlo funzionare, è sufficiente recuperare il blocco 'script' nel layout. Puoi anche semplicemente scrivere il file .js su un altro blocco di visualizzazione.

Puoi verificarlo qui: https://github.com/dizyart/cakephp-viewautoload

E 'nelle prime fasi, in modo da assicurarsi di commentare e lista dei desideri!

0

LI lavorato un po '(molto poco) po' sopra W1ckd frammento e ha reso più facile per condividere gli stessi js per diverse azioni:

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); 
} 

questo modo si può avere qualcosa di simile:

Webroot/js/regolatore/view.edit.add.js

e questo JS sarà incluso nel quei tre ac tions (visualizza, modifica, aggiungi).

0

Con Cake v3 puoi farlo in questo modo. Aggiungi gli script che desideri nel controller specifico.

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

impostare il valore predefinito di inizializzare e rendere una volta //AppController.php funzione initialize pubblica() { parent :: initialize();

$this->scripts = []; 
} 

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

Ora è possibile eseguire questa funzione una volta.

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