2010-11-17 16 views
8

Je suis en train de réorganiser un Play! projet où il y a beaucoup de code JS dans les fichiers modèles HTML. Ce code doit être déplacé vers des fichiers JS externes pour une meilleure lisibilité et des temps de chargement de page plus rapides. Toutefois, lorsque je viens de créer un fichier JS dans le dossier public, tous les remplacements de lien @ {Controller.method} ne fonctionnent plus. Je pensais à appeler une fonction d'initialisation à partir du HTML modèles qui fournit seulement les URL nécessaires commeJouez! Framework: meilleure pratique pour utiliser des URL dans des fichiers JavaScript distincts?

initialize({ "Application.doThis" : "@{Application.doThis}"}) 

mais cela devient très lourd et sujette à erreur avec une URL qui est ajouté. Une autre chose est, que le I18N ne fonctionne plus. Donc quelle est la meilleure pratique pour des scénarios comme ceux-ci, où vous avez votre code JS dans un fichier séparé, mais souhaitez toujours utiliser la génération d'URL et I18N dans votre JS?

Répondre

12

Dans le modèle principal, générer un 'routeur Javascript', quelque chose comme:

<script> 
    var routes = { 
     doThis: #{jsAction @Application.doThis(user, ':param1', ':param2') /}, 
     doThat: #{jsAction @doThat() /} 
    } 
</script> 

Et puis dans un fichier javascript 'statique', utilisez ce routeur:

$.get(routes.doThis({param1: x, param2: 'yop'})) 
+1

Merci. C'est ce que j'avais en tête, mais cela signifie en fait que j'ai besoin de beaucoup de code standard que je dois prolonger chaque fois qu'une nouvelle route arrive, ce qui est facile à oublier. Une autre chose est l'utilisation de i18n pour les messages en JavaScript, on pourrait bien sûr écrire un tel "routeur" pour les messages, mais cela duplique efficacement toutes les clés I18N en JavaScript. –

+0

Vous pouvez déjà utiliser la balise # {18n /}. Je suppose que nous pourrions fournir une balise qui exposerait le fichier entier via javascript, mais cela pourrait entraîner des problèmes de sécurité. –

+0

Ok, merci beaucoup! –

5

L'astuce est pour obtenir le framework pour analyser votre javascript, ou votre CSS, ou n'importe quoi d'autre dans les répertoires statiques. Voici une solution facile.

Ajouter un contrôleur controllers.StaticParser:

package controllers; 
import play.mvc.Controller; 

public class StaticParser extends Controller { 
    public static void parse(String route) { 
     render("/" + route); 
    } 
} 

Pour ajouter votre fichier conf/routes:

GET /parse/{<.*>route} StaticParser.parse 

L'expression rationnelle dans cette voie est très important, sinon vous ne pouvez pas ajouter pathing à la demande. Pour demander une ressource statique analysé, comme un script js, utilisez:

<script src="/parse/public/javascripts/test.js" 
    language="javascript" type="text/javascript" ></script> 

Malheureusement, vous ne pouvez pas utiliser le format #{script 'test.js' /}, car la balise de script recherche le fichier statique. Pour corriger cet irritant, voici un hack éhonté de la balise script: la balise #{parsescript 'test.js'/}. Il devrait aller à /views/tags/parsescript.tag:

{ 
* insert a parsescript tag in the template. 
* by convention, referred script must be put under /public/javascripts 
* src  (required) : script filename, without the leading path "/public/javascripts" 
* id  (opt.)  : sets script id attribute 
* charset (opt.)  : sets source encoding - defaults to current response encoding 
* 
* #{parsescript id:'datepicker' , src:'ui/ui.datepicker.js', charset:'${_response_encoding}' /} 
}* 
%{ 
    (_arg) && (_src = _arg); 

    if (!_src) { 
     throw new play.exceptions.TagInternalException("src attribute cannot be empty for script tag"); 
    } 
    _src = "/public/javascripts/" + _src 
    try { 
     _abs = play.mvc.Router.reverseWithCheck(_src, play.Play.getVirtualFile(_src), false); 
    } catch (Exception ex) { 
     throw new play.exceptions.TagInternalException("File not found: " + _src); 
    } 
}% 
<script type="text/javascript" language="javascript"#{if _id} id="${_id}"#{/if}#{if _charset} charset="${_charset}"#{/if} src="/parse${_abs}"></script> 

Il fonctionne exactement comme la balise #{script /}, mais le fichier avant parse retourner: #{parsescript 'test.js' /}

On pourrait tout aussi pirater sans vergogne l'étiquette #{stylesheet /}, mais je pense avoir pris assez d'espace déjà.