最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Play! Framework: Best practice to use URLs in separate JavaScript files? - Stack Overflow

programmeradmin4浏览0评论

I am currently reorganizing a Play! project where there is a lot of JS code in the HTML template files. This code should be moved to external JS files for better readability and faster page loading times. However, when I just create a JS file in the public folder, all the @{Controller.method} link replacements are no longer working. I was thinking about calling some initialization function from the HTML templates which just supplies the required URLs like

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

however this is being very cumbersome and error-prone with any URL that is added. Another thing is, that the I18N also no longer works. So what is the best practice for scenarios like these, where you have your JS code in a separate file but still want to use URL generation and I18N in your JS?

I am currently reorganizing a Play! project where there is a lot of JS code in the HTML template files. This code should be moved to external JS files for better readability and faster page loading times. However, when I just create a JS file in the public folder, all the @{Controller.method} link replacements are no longer working. I was thinking about calling some initialization function from the HTML templates which just supplies the required URLs like

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

however this is being very cumbersome and error-prone with any URL that is added. Another thing is, that the I18N also no longer works. So what is the best practice for scenarios like these, where you have your JS code in a separate file but still want to use URL generation and I18N in your JS?

Share Improve this question edited Apr 19, 2011 at 21:53 Jonas 129k101 gold badges327 silver badges405 bronze badges asked Nov 17, 2010 at 21:38 Jan ThomäJan Thomä 13.6k6 gold badges60 silver badges84 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 12

In the main template, generate a 'Javascript router', something like:

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

And then in any 'static' javascript file, use this router:

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

The trick is to get the framework to parse your javascript, or your CSS, or anything else in the static directories. Here's an easy solution.

Add a controllers.StaticParser controller:

package controllers;
import play.mvc.Controller;

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

To your conf/routes file add:

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

The regexp in that route is very important, otherwise you can't add pathing to the request. To request a parsed static resource, such as a js script, use:

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

Unfortunately, you can't use the #{script 'test.js' /} format, because the script tag looks for the static file. To correct that irksome-ness, here's a shameless hack of the script tag: the #{parsescript 'test.js'/} tag. It should go to /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>

It works exactly like the #{script /} tag, but parses the file before returning it: #{parsescript 'test.js' /}

One could equally shamelessly hack the #{stylesheet /} tag, but I think I've taken up enough space already.


发布评论

评论列表(0)

  1. 暂无评论