2010-11-17 11 views
8

Obecnie reorganizuję grę! projekt, w którym jest dużo kodu JS w plikach szablonu HTML. Ten kod powinien zostać przeniesiony do zewnętrznych plików JS , aby uzyskać lepszą czytelność i szybsze ładowanie stron. Jednak po utworzeniu pliku JS w folderze publicznym wszystkie zamienniki łącza @ {Controller.method} przestały działać. Byłem myśleć o nazywając jakąś funkcję inicjalizacji z HTML szablony, które po prostu dostarcza wymaganych adresów jakGraj! Framework: Najlepsza praktyka używania adresów URL w oddzielnych plikach JavaScript?

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

jednak to staje się bardzo uciążliwe i podatne na błędy z dowolnego adresu URL który jest dodawany. Inną sprawą jest to, że I18N również nie działa. Tak więc jaka jest najlepsza praktyka w takich scenariuszach, gdzie masz kod JS w oddzielnym pliku, ale nadal chcesz używać generowania adresów URL i I18N w swoim JS?

Odpowiedz

12

W głównym szablonie wygenerować 'routera Javascript', coś jak:

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

A potem w dowolny 'statyczne' javascript plik, użyj tego routera:

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

Dziękuję. To właśnie miałem na myśli, ale to oznacza, że ​​mam dużo kodu, który muszę rozpoczynać za każdym razem, gdy pojawi się nowa trasa, którą łatwo zapomnieć. Inną rzeczą jest używanie i18n dla wiadomości w JavaScript, można oczywiście napisać taki "router" również dla wiadomości, ale to skutecznie powiela wszystkie klucze I18N w JavaScript. –

+0

Możesz już używać znacznika # {18n /}. Sądzę, że możemy dostarczyć znacznik, który eksponuje cały plik trasy przez javascript, ale może to prowadzić do problemów bezpieczeństwa. –

+0

OK, dziękuję bardzo! –

5

Sztuką jest uzyskać framework do parsowania twojego javascriptu, twojego CSS lub cokolwiek innego w statycznych katalogach. Oto proste rozwiązanie.

Dodaj controllers.StaticParser Kontroler:

package controllers; 
import play.mvc.Controller; 

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

do swojej conf/routes plików dodatek:

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

RegExp w tej trasie jest bardzo ważne, w przeciwnym razie nie można dodać pathing do wniosku. Aby zażądać analizowany zasobów statycznych, takich jak skrypt js, użyj:

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

Niestety, nie można korzystać z formatu #{script 'test.js' /}, ponieważ tag skrypt szuka pliku statycznego. Aby poprawić tę irytującą-ność, oto bezwstydny hack tagu skryptu: tag #{parsescript 'test.js'/}. Należy udać się do /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> 

To działa dokładnie tak jak tagu #{script /}, ale analizuje plik przed wpuszczeniem go: #{parsescript 'test.js' /}

Jeden mógłby równie bezwstydnie hack tag #{stylesheet /}, ale myślę, że już podjęte dostatecznie dużo miejsca.