Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonjour,
Vous vous souvenez, il y a 2 mois, j'étais un petit débutant qui n'y comprennait rien à Zend. Aujourd'hui je suis toujours un débutant, mais j'ai presque fini mon premier projet Zend !
Celui-ci est en MVC, il est doté de plusieurs modules, et il a tout un tas d'intéractions Javascript et AJAX qui apportent une forte interactivité au site, notamment grâce à JQuery...
Ma question est alors : comment charger proprement des scripts javascript, en fonction du controller et de l'action.
Jusqu'a présent je procède d'une manière sale (enfin je pense):
mavue.phtml
<script type="text/javascript"> .... mon script javascript/jquery ...... </script> <h2>Mon titre</h2> <?php echo $this->mon truc ?>
Chaque vue comporte un script différent, j'ai donc un script javascript pour chaque action de chaque controller.
J'aimerai donc connaitre une bonne façon d'organiser tout ça.
Faut-il que ce soit le controller qui charge le script adéquate?
Comment organiser mes fichiers js ?
J'avais pensé à un truc du genre :
/mesjavascripts/controller1/script_action1.js
/mesjavascripts/controller1/script_action2.js
/mesjavascripts/controller2/script_action1.js
(et la question est : oui mais ensuite comment on charge ces fichiers? Ce serait pas propre que ce soit le controlleur qu'il le fasse (plutot que de le mettre dans la vue).
Par avance merci bien.
Hors ligne
pour ma part je ne mets aucun code javascript dans le php
il sont tous dans des fichiers js statique.
ainsi il ne sont chargé qu'une fois par le navigateur (le moteur JS les compile et les mets en cache) du coup le chargement des pages est rapide (à par la première fois)
dans mon dernier projet je n'ai qu'une seule page html vide (elle contient body et un div que j'efface après le démarrage) cette page charge tous les javascript (avec une image pour patienter dans le div que je vais effacer)
ces javascript construisent l'IHM et appelle le serveur pour les données. le temps de chargement est de l'ordre de 3,5 seconde pour 26 000 lignes de code javascript + la lib extjs (30 000 lignes de php)
une fois l'IHM chargée tout est extrêmement réactif seules les données circulent entre le client et le serveur.
c'est un cas plutôt extrême ou mon application est full Ajax. sinon je mets la lib de base dans le layout principal de mes pages et les scripts nécessaire à la page en référence dans la page.
mais je ne fais pas un js par page mais plutôt un js par composant ainsi je réutilise les scripts dans plusieurs pages.
récemment mais de façon plus expérimentale j'ai développé une petite application ou l'IHM est en Javascript développé avec un framework MVC développé à partir de ExtJs dans ce framework j'ai mis en place le chargement dynamique des composant.
comme dans ma grosse appli l'application démarre sur une page HTML vide et c'est le framework js qui lance l'IHM
la différence seul les composants nécessaire lors du démarrage sont chargés. les autres le sont lorsque les composants sont activés.
ainsi le temps de chargement de l'application est réduit et le premier appel à un composant un peut ralenti. pour des composants complexes comme un crud complet (présentation d'un grid de données paginées, rechercher, formulaire d'ajout modification et diverses boites de dialogue et notification entre autre pour la suppression)
le temps du premier chargement est passe de 255ms à 360ms c'est donc largement exploitable.
A+jyt
Hors ligne
J'ait opté pour la méthode un seul fichier javascript. Tout est compressé dedans.
Il est donc chargé une seule fois comme l'explique bien sekaijin. Le code de tout mon site est dedans.
Après pour détécter si je dois "lancer" tel ou tel partie du code js, je fais des truc du genre
$detecteur = $('#divQuiNecessiteLeCodeCiApres'); if ($detecteur.length == 1) { //... ici mon code pour tel partie }
Ca vaut ce que ça vaut. Je me suis jamais demandé si je pouvais faire mieux, mais jusqu'à aujourd'hui ça me va. Je trouve ca plus maintenable que d'avoir tout dans les vues. Quand je regarde le code JS de Facebook ça me donne des frissons. Et je trouve que ça galère un peu. Après chaque méthode doit avoir des avantages et des inconvénients.
Hors ligne
Mr.MoOx a écrit:
J'ait opté pour la méthode un seul fichier javascript. Tout est compressé dedans.
Il est donc chargé une seule fois comme l'explique bien sekaijin. Le code de tout mon site est dedans.
Après pour détécter si je dois "lancer" tel ou tel partie du code js, je fais des truc du genreCode:
$detecteur = $('#divQuiNecessiteLeCodeCiApres'); if ($detecteur.length == 1) { //... ici mon code pour tel partie }Ca vaut ce que ça vaut. Je me suis jamais demandé si je pouvais faire mieux, mais jusqu'à aujourd'hui ça me va. Je trouve ca plus maintenable que d'avoir tout dans les vues. Quand je regarde le code JS de Facebook ça me donne des frissons. Et je trouve que ça galère un peu. Après chaque méthode doit avoir des avantages et des inconvénients.
oui avec jquery tu a un oppérateur genre
$('#divQuiNecessiteLeCodeCiApres').each({ //... ici mon code pour tel partie });
A+JYT
Dernière modification par sekaijin (11-05-2009 12:47:13)
Hors ligne
Presque pareil que Moox, le code qui se reproduit souvant est dans un seul fichier.
Pour des codes spécifiques à une action, j'ai un plugin qui test la présence d'un fichier js correspondant à l'action et l'inclus si il le trouve.
Par contre, pas besoin de if pour moi, si $() ne trouve pas son object, il ne se passe rien, c'est tout.
Hors ligne
Vous entendez quoi par "chargement du fichier javascript" ?
C'est un include ? Vus avez une procédure particulière ?
Pour Dojo j'ai compilé les librairies que j'utilise, mais est il possible de faire ça "à la volée" ?
Hors ligne
A la volée, ca serait du temps serveur de gâché...
Hors ligne
Et pour le chargement, c'est un include ou équivalent, non ?
Hors ligne
Un include javascript c'est en html :
<script src="/path/file.js" type="text/javascript"></script>
Lorsque tu utilises cette méthode, le js est mis en cache et donc n'est pas "recompilé" à chaque page.
NB: perso je charge les js en fin de page, ca permet un rendu html/css plus rapide des pages
Hors ligne
On est d'accord, je voulais être certain de parler de la même chose...
Hors ligne
Bonjour et merci pour toutes ces réponses.
Je voudrais bien tout chargé dans un seul fichier javascript, seulement peut etre qu'il va exister le problème suivant :
imaginez un div #monDiv sur la page a.phtml et un autre #monDiv sur la page b.phtml,
pour chaque page(vue), on doit faire une action differente sur #monDiv , comment javascript (jquery), va savoir quelle action il doit faire ?
J'ai imaginé (mais pas mis en pratique), une solution qui se calque sur la structure mvc de Zend:
on creer un modele JavaScriptGenerator et dans le controller on fait ca :
$this->view->javascript=new JavaScriptGenerator('controller','action')
puis dans la vue, il faudra faire un truc du genre :
echo $this->javascript
l'astuce serait ensuite de bien classer ses codes javascript :
-javascript
--controller1
action1.js
action2.js
--controller2
action1.js
action2.js
De la même façon, on pourra faire un dossier 'common'
ainsi la méthode toString de JavaScriptGenerator génèrera un code du genre :
<script src="/javascript/Controller/Action.js" type="text/javascript"></script>
On peut même essayer d'automatiser le truc (mais là je ne sais pas comment).
Peut-être dans un plug in qui se chargerait de voir si le fichier javascript existe, et si c'est le cas il génère le bon code dans la vue....
Qu'en pensez vous?
Merci bien
Hors ligne
nORKy a écrit:
Pour des codes spécifiques à une action, j'ai un plugin qui test la présence d'un fichier js correspondant à l'action et l'inclus si il le trouve.
Tu pourrais nous partager ça ?
Hors ligne
A oui exact, merci de faire remarquer cette phrase, ca répond en partie à l'idée que j'avais...
Hors ligne
perso je fais des fichier js séparé
et je mets des id explicite sur mes éléments
monDIV n'a pas de sens
par contre gridClient formClient userProfile oui
et il y a peut de chance d'avoir des conflits
A+JYT
Hors ligne
Mr.MoOx a écrit:
nORKy a écrit:
Pour des codes spécifiques à une action, j'ai un plugin qui test la présence d'un fichier js correspondant à l'action et l'inclus si il le trouve.
Tu pourrais nous partager ça ?
Très simple
class My_Controller_Plugin_ViewSetup extends Zend_Controller_Plugin_Abstract { protected $_view; public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request) { $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $viewRenderer->init(); $this->_view = $viewRenderer->view; } public function preDispatch(Zend_Controller_Request_Abstract $request) { $this->_actionJSLink($request); } protected function _actionJSLink(Zend_Controller_Request_Http $request) { $view = $this->_view; $module = $request->getModuleName(); $controller = $request->getControllerName(); $action = $request->getActionName(); $file = APPLICATION_PUBLIC . '/js/' . $module . '.' . $controller . '.' . $action . '.js'; if (file_exists($file)) { $url = $view->baseUrl() . '/js/' . $module . '.' . $controller . '.' . $action . '.js'; $view->headLink()->appendStylesheet($url); } } }
Donc si un js de type module.controller.action exists, il l'inclus dans l'entête.
C'est très simple
Dernière modification par nORKy (13-05-2009 11:39:08)
Hors ligne
Hello,
@nORKy: headLink? Stylesheet? => c'est pas headScript
A+
Hors ligne
euh oui, y'a un bug de copier coller car biensur tu peux faire la même chose avec les styles CSS
bien vu
Hors ligne
Vraiment très intéressant !
merci beaucoup !
Hors ligne
Salut!
Je suis en train de mettre en place ce fameux plugIn proposé par nOrKy,
J'ai remplacé la ligne :
$view->headLink()->appendStylesheet($url);
par
$view->headScript() -> appendFile(url);
C'est ce qui a été suggéré par Mikaelkael.
Cela dit, j'ai l'erreur suivante:
Notice: Use of undefined constant APPLICATION_PUBLIC - assumed 'APPLICATION_PUBLIC'
Il manque des quotes c'est bien ca?
merci
Hors ligne
Ca veu dire que t'as un appel à la constante APPLICATION_PUBLIC alors qu'elle n'est pas défini.
Donc du coup ça remplace par la chaine "APPLICATION_PUBLIC"...
Hors ligne
Oui oui je sais, c'est surement une variable spécifique a ton programme a toi.
Après quelques corrections, ca fonctionne. Cependant, je pense avoir trouvé quelques limites.
Il s'agit des requêtes ajax, en utilisant JQUERY.
Je m'explique. Quand je fais un appel AJAX, j'appelle en fait l'url classique module/controller/action/parametres....
Bien sur, dans le controller je désactive le layout.
Seulement, les nouveaux éléments de ma page html qui viennent d'être inscrusté dans ma page, à l'aide de la requete Ajax, comportent eux aussi des évènements javascript.
Je ne sais pour quelle raison, mais pour que les évènements sur les nouveaux élements soient effectif, je dois importer le javascript en même temps que la réponse AJAX.
Il faut donc que je fasse un echo $view->headScript à chaque requête AJAX, non?
La question que je me pose donc, c'est : est-ce que si je crée un plugIn comportant une méthode pré-dispatch, je vais passer par cette méthode même en cas de requête AJAX ? (et donc dans cette méthode, je ferais un echo $this->headScript())
Est-ce correct?
merci bien.
Hors ligne
D'après moi oui tu as tout bon. Le plugin sont exécutés que ce soit ajax ou pas.
Le layout est "executé" en dernier, il n'a aucune influence sur le reste de la requête (sauf si dedans tu fais appel a des actions )
Par contre attention, jQuery n'interprète pas les <scripts> qui arrivent dans les retours ajax. Il faut utilisés $.getScript(). Ou alors tout avoir dans ton fichier principal et déclencher un trigger par une detection d'id ou de classe.
Hors ligne
Merci pour ces infos,
Je suis pas sur de comprendre la deuxieme partie de ton message. Jusqu'à présent je faisais un truc du genre :
$.ajax( .................... success(msg){ $("#mondiv").html(msg) }
et dans mon msg, qui correspond en fait au code html de ma vue rendue :
<script type="text/javascript"> tout mon code javascript.... </script> ....mon code html ensuite.....
et ca marchait!
je suis un peu dans le flou...je vais faire des recherches sur getscript.
merci
Hors ligne
Finalement, c'est pas aussi simple que cela en a l'air!
Je m'explique:
Avec le PlugIn de (edit) nORKy, on ajoute le fichier javascript a la fin de la liste, puis dans le layout on "echo" tout ca.
Le dernier fichier javascript ajouté est celui qui est spécifique a l'url et forcement il doit utiliser les librairies (qui ont déja été ajoutées avant).
J'ai donc crée un plugIn sur le même modèle de (edit) nORKy, à la différence que celui-ci echo echo '<script type="text/javascript" src="'.$url.'"/>';
Seulement il y a deux problèmes :
- On ne peut pas mettre ce bout de code au bon endroit,
- Comment tester qu'il s'agit d'une requête ajax ?
J'en viens donc à l'idée suivante (mais pas terrible):
Il faut, a chaque réponse de requete ajax, recupérer le script de la nouvelle vue qu'on va afficher...à l'aide de $.getScript (ce qui rejoint la remarque de mr. Moox).
Dernière modification par Mr.MoOx (19-05-2009 14:40:26)
Hors ligne
- Comment tester qu'il s'agit d'une requête ajax ?
Dans un controller
$this->_request->isXmlHttpRequest()
Moi perso sur mon appli (musity.fr) j'ai un mega fichier js avec tout le code pour le site. Et du coup je fais aucun getScript. Je trouve pas que mon site rame niveau client. Méthode à voir. Ou pas.
Hors ligne