2010-11-17 16 views
8

¡Actualmente estoy reorganizando una Play! proyecto donde hay una gran cantidad de código JS en los archivos de plantilla HTML. Este código se debe mover a los archivos JS externos para una mejor legibilidad y tiempos de carga de página más rápidos. Sin embargo, cuando solo creo un archivo JS en la carpeta pública, todos los reemplazos de enlaces @ {Controller.method} ya no funcionan. Estaba pensando en llamar a alguna función de inicialización del HTML plantillas que solo suministra la URL solicitada como¡Juego! Marco: ¿práctica recomendada para usar URL en archivos JavaScript separados?

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

sin embargo, esto se está convirtiendo en muy engorroso y propenso a errores con cualquier URL que se agrega. Otra cosa es que el I18N tampoco funciona. Entonces, ¿cuál es la mejor práctica para escenarios como estos, donde tiene su código JS en un archivo separado pero todavía quiere usar generación de URL y I18N en su JS?

Respuesta

12

En la plantilla principal, generar un 'router de Javascript', algo así como:

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

Y a continuación, en cualquier 'estática' javascript archivo, utilice este router:

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

Gracias. Esto era lo que tenía en mente, sin embargo, eso significa que tengo que escribir un código repetitivo que tengo que extender cada vez que aparece una nueva ruta, que se olvida fácilmente. Otra cosa es usar i18n para mensajes dentro de JavaScript, uno podría por supuesto escribir un "enrutador" para mensajes también, pero esto efectivamente duplica todas las claves I18N en JavaScript. –

+0

Ya puede usar la etiqueta # {18n /}. Supongo que podríamos proporcionar una etiqueta que exponga todo el archivo de ruta a través de JavaScript, pero podría generar problemas de seguridad. –

+0

Ok, muchas gracias! –

5

El truco es para obtener el marco para analizar su javascript, o su CSS, o cualquier otra cosa en los directorios estáticos. Aquí hay una solución fácil.

Agregar un controlador controllers.StaticParser:

package controllers; 
import play.mvc.Controller; 

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

Para su conf/routes archivo de complemento:

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

La expresión regular en esa ruta es muy importante, de lo contrario no se puede agregar encauzamiento a la solicitud. Solicitar un recurso estático analizado, como un script js, utilice:

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

Por desgracia, no se puede utilizar el formato #{script 'test.js' /}, debido a que la etiqueta de script busca el archivo estático. Para corregir ese fastidio, aquí hay un truco desvergonzado de la etiqueta del script: la etiqueta #{parsescript 'test.js'/}. Se debe ir a /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> 

funciona exactamente igual que la etiqueta #{script /}, pero analiza el archivo antes de devolverlo: #{parsescript 'test.js' /}

Se podría igualmente descaradamente cortar la etiqueta #{stylesheet /}, pero creo que he tomado suficiente espacio ya


Cuestiones relacionadas