Scala template engine for creating js files - scala

I want to create js files using a template engine with Scala. Is it possible with the popular templating engines for Scala, namely Play and Scalate? If possible, than what are the pros and cons for using either of them?

Just create view with .js ext, i.e.: app/views/myScript.scala.js and dummy content:
#(message: String)
alert("#message");
Then add an action into your controller:
def myScript = Action {
// use views.js... NOT views.html... !
Ok(views.js.myScript.render("Whoha! I'm dynamic JS in Scala :)"))
}
or in Java version:
public Result myScript(){
// use views.js... NOT views.html... !
return ok(views.js.myScript.render("Yey! I'm dynamic JS in Java :)"));
}
Add the route to this action:
GET /my-script controllers.Application.myScript()
So you can use this route directly:
<script src="/my-script"></script>
note, that Play should return valid Content-Type:text/javascript; charset=utf-8 in the response, anyway depending on version you are using it may be required to enforce this manually within your action (use browser's inspection tool to check the response type)

It really depends on what you want to achieve, i.e. how sophisticated your JavaScript code will be, but, unless it's something really small and simple, I'd suggest using the Scala.js. This way you basically will write some Scala code that will compile into JavaScript, and that compiled JavaScript you should be able to include into your Play application.
Advantages of writing Scala vs JavaScript should be pretty obvious (type safety, using lots of the existing Scala libraries). Disadvantage would be some delays for Scala -> JavaScript compilation, and also lack of the same seamless integration of Scala.js and Play, like Play has with its own templating engine. It's up to you to decide if the extra work to make these 2 work together worth it.

Related

In Scala.JS is there a call to get the platform I'm running on?

I have some Scala code for a library which I compile for both the JVM and ScalaJS.
Right now I have a "pure" project, without special code in the js and jvm proojects, and I'd like to keep it that way due to intellij integration and some other factors.
However, I do have a small bit of code (1-2 lines) that needs to change based on whether I'm in the JVM or JS. I'd like an easy way to accomplish this that doesn't require me changing my whole project structure.
Basically I'd like a call "isJS" that returns true if I'm on JavaScript and false otherwise.
There is nothing standard, as it would require to extend the API available on the JVM, which Scala.js cannot do.
You can build it yourself easily with a tiny object Platform with two different implementations in the js/ and jvm/ subprojects. For example for JS it would be:
object Platform {
final val isJS = true
final val isJVM = false
}
Of course that requires to be non-pure. You could also abstract that in a tiny library offering only that feature. That is what the platform project of catalysts does, for example.
If you want to keep completely pure and no dependency, you have to resort to a hack:
val isJS = 1.0.toString == "1"
This works because, on the JVM, 1.0.toString returns "1.0", but on JS it returns "1".
You can do:
val isJS = System.getProperty("java.vm.name") == "Scala.js"

How can I write a code generator in Ceylon

I want to write a code generator that generates a class based on the meta model of another ceylon class. I want the code generator to run at compile time. What is the best way for me to do this. I could probably accomplish this by writing a plugin for gradle or the ceylon build system but I'm hoping for a simpler solution. Unfortunately, I don't see any support for code generators in ceylon. Also, are there any plans for code generators in ceylon?
I want to write this code generator because I'm thinking about writing a simple web framework for ceylon that look at a class like the following using the meta-model:
controller
shared class Controller() {
shared void doSomething() => print("did it!");
}
I plan for it to be like Spring MVC. This framework would make a restful API from the Controller class that allows someone to write an AJAX call like this:
$http.get("/Controller/doSomething");
I want to make things more convenient, high level, and simple by doing something like GWT. I want to create a code generator that automatically generates a class like this:
shared class RemoteController() {
shared void doSomething() {
$http.get("/Controller/doSomething");
}
}
The RemoteController would be run in a user's browser as javaScript and allow client side ceylon code to do an Ajax call like this:
RemoteController().doSomething();
That would end up calling the Controller().doSomething() on the server so "did it!" would be printed.
AST Transformers have been proposed, but are still in the early design phase. For now, to do compile-time code generation, you’ll have to rig up something of your own.
To actually generate the code, I would recommend use of ceylon.ast and ceylon.formatter. The workflow would roughly be:
analyze source code –
either parse it with ceylon.ast (ceylon.ast.redhat::compileAnyCompilationUnit) and analyze it without typechecking,
or parse it using the compiler, run the typechecker, then convert it to ceylon.ast (ceylon.ast.redhat::anyCompilationUnitToCeylon), keeping the typechecker information using the new update hooks in the very soon upcoming 1.2.0 release
edit the source code AST to add your new code (using a custom ceylon.ast.core::Editor that injects new class definitions into the CompilationUnits), or perhaps create entirely new compilation units if the RemoteController lives in a different module
convert the ceylon.ast AST to a compiler AST and feed it into ceylon.formatter to turn the AST into code again (see here for an example of that)
Alternatively, if you integrate this into your build step, you could skip the ceylon.formatter part of step 3 and instead feed the converted compiler AST into the typechecker and rest of the compiler directly.

GWT Client Server Communication

I'm wondering whether it is at all possible to make the client ask the server for a given string, and incorporate it into another string ?
I don't see how to do that using the async approach.
As far as I know there is no really simple way to do this, because the i18n machanism of GWT replaces strings at compile-time and not at runtime.
You can try one of the following approaches:
Load the i18n in your entrypoint, store all messages in a local Map and create the Label etc, with the values from you cache. PRO: all GWT standard CONS: one request more, before you can show a translated page
Use JSP and no HTML at serverside. Wthin you jsp can create a JSON from your
message.properties and put it into your hostpage. PRO: You can synchronous read te values CONS: You will need to write a JSP which reads the properties for the correnct language, You will need to write a JSNI method to load the translated values.
Rethink, if you need a different way of translation. The built-in i18n will create tranlated versions of your app at compile-tim
I think I would use the second approach.

How to access data across modules in GWT?

I have two GWT modules with its own entry point, ModuleA and ModuleB. I am using Window.assign() to move from ModuleA to ModuleB. One Variable value is set in ModuleA. How to access the same value from ModuleB?
Thanks in advance.
I have written a couple of answers which could help you to deal with this.
Since you cannot share pure java between two compiled modules: GWT: How to share a java Object (ie: EventBus) between two modules, I suggest to export methods using jsni: How to communicate two modules in GWT. But I would use gwt-exporter or gwt-query to avoid writing js by hand which normally is a source of mistakes: Calling GWT Java function from JavaScript
Note, that these solutions only work in the case both modules are loaded in the same html.
If you want to pass a value to a different page downloading the actual, you can append those values to the new url and read it in the second application:
// Module A
Window.Location.assign("module_B.html?msg=whatever");
// Module B
String msg = Window.Location.getParameter("msg");
IMO the best way would be to implement the observer/observable pattern in pure JavaScript in your host page, and use JSNI in your application to register handlers/fire events.

gwt lazy loading

Is it possible in a large GWT project, load some portion of JavaScript lazy, on the fly?
Like overlays.
PS: Iframes is not a solution.
Check out GWT.runAsync as well as the Google I/O talk below, which goes into lazy loading of JavaScript in GWT projects.
http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting
http://code.google.com/events/io/sessions/GoogleWavePoweredByGWT.html (around time 25:30)
I think this is what you are looking for.
<body onload="onloadHandler();">
<script type="text/javascript">
function onloadHandler() {
if (document.createElement && document.getElementsByTagName) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = './test.js';
var heads = document.getElementsByTagName('head');
if (heads && heads[0]) {
heads[0].appendChild(script);
}
}
}
function iAmReady(theName) {
if ('undefined' != typeof window[theName]) {
window[theName]();
}
}
function test() {
// stuff to do when test.js loads
}
</script>
-- test.js
iAmReady('test');
Tested and working in Firefox 2, Safari 3.1.2 for Windows, IE 6 and Opera 9.52. I assume up-level versions of those should work as well.
Note that the loading is asynchronous. If you attempt to use a function or variable in the loaded file immediately after calling appendChild() it will most likely fail, that is why I have included a call-back in the loaded script file that forces an initialization function to run when the script is done loading.
You could also just call an internal function at the bottom of the loaded script to do something once it has loaded.
GWT doesn't readily support this since all Java code that is (or rather may be) required for the module that you load is compiled into a single JavaScript file. This single JavaScript file can be large but for non-trivial modules it is smaller than the equivalent hand written JavaScript.
Do you have a scenario where the single generated JavaScript file is too large?
You could conceivably split your application up into multiple GWT modules but you need to remember that this will limit your ability to share code between modules. So if one module has classes that reference the same class that another module references, the code for the common class will get included twice.
Effectively the modules create their own namespace, similar what you get in Java if you load the same class via two separate class loaders. In fact because the GWT compiler only compiles in the methods that are referenced in your code (i.e it does dead code elimination), it is conceivable that one module will include a different subset of methods from the common class to the other module.
So you have to weigh up whether loading it all as one monolithic module and taking an upfront hit the first time round is better than having multiple modules whose cumulative code size might well be significantly greater than the single module approach.
Given that GWT is designed so that the user should only ever load the same version of a module once (it is cached thereafter), in most cases the one off upfront hit is preferable.
Try to load a big GWT application with the "one upfront" approach using a iPhone or an iPod touch...it will never load.
The module approach is a but more complexe to manage but better for smaller client devices.
Now, how do I load a module from my Java code without using an iFrame?
Erick