I have an HTML file to test a web application composed of several Fantom generated JavaScript files. Everything runs fine.
Now I'm trying to do the same thing, but instead of using the HTML file, I want to dynamically load the generated JavaScript files, which are contained in the pods.
The closest example I have encountered is the js demo, but I don't completely understand it, and it seems overcomplicated to my purposes (I don't want to compile any Fantom code on the fly, I just want to use already generated JavaScript). So I've tried my luck simplifying things to something like this:
using util
using web
using webmod
using wisp
class Demo : AbstractMain
{
@Opt { help = "http port" }
Int port := 8080
override Int run()
{
wisp := WispService
{
it.port = this.port
it.root = DemoMod()
}
return runServices([wisp])
}
}
const class DemoMod : WebMod
{
override Void onGet()
{
res.headers["Content-Type"] = "text/html; charset=utf-8"
res.out.docType
res.out.html
res.out.head
res.out.title.w("Demo").titleEnd
res.out.includeJs(`/pod/sys/sys.js`)
res.out.includeJs(`/pod/web/web.js`)
res.out.includeJs(`/pod/gfx/gfx.js`)
res.out.includeJs(`/pod/dom/dom.js`)
res.out.includeJs(`/pod/helloJsStep2/helloJsStep2.js`)
res.out.includeJs(`/pod/helloJsStep2Demo/helloJsStep2Demo.js`)
res.out.headEnd
res.out.body
res.out.script.w(getJs()).scriptEnd
res.out.bodyEnd
res.out.htmlEnd
}
Str getJs()
{
Str js := "var demo = fan.helloJsStep2Demo.JsLibWrapperDemo.make();\n"
js += "demo.run();\n"
return js
}
}
Now, this code doesn't run in the browser, because "fan is not defined" (according to firebug).
It is clear that the res.out.includeJs(...) lines are not fetching the js files from the pods. But if that is so, how come this works without problem in the js demo?
Is there any simple way to do what I need?
Thanks!
Yuri StrotMon 28 Jun 2010
The problem is you construct index page for any request to server. When browser loading content of js file it hook the same DemoMod.onGet method and get index content instead of js file.
js demo handle this situation correctly:
override Void onGet()
{
//check uri first
name := req.modRel.path.first
if (name == null)
onIndex // load index page for `http://yoursite.com/`
else if (name == "pod")
onPodFile //load file from pod for `http://yoursite.com/pod/...`
}
** This method fetching resources from the pods
Void onPodFile()
{
// serve up pod resources
File file := ("fan://" + req.uri[1..-1]).toUri.get
if (!file.exists) { res.sendErr(404); return }
FileWeblet(file).onService
}
Void onIndex()
{
...
}
dfreireMon 28 Jun 2010
ystrot, thanks for the reply, but as far as I understand, that serves one static file of one pod, but it does not serve several static contents of several pods, as it would be done in an html file.
(Having a single index page for any request to server is not a problem for me at the moment.)
andyMon 28 Jun 2010
dfreire - you actually have two problems. The first, as ystrot noted, you need to modify your DemoMod to serve up the pod js files. Once that is fixed you will see the second, which is you're trying to execute js before you have loaded the dependencies. If you plan to call any Fantom APIs in your webpage - you must do so in your onLoad callback to guareente you have everything you need.
dfreireMon 28 Jun 2010
andy, thanks but I don't get it yet...
Using the FileWeblet, I can only serve the js files of one pod, right? What if (as it is my case) I want to serve js files spread from different pods?
What if (as it will be my case in the future) I also want to link to external js files?
To clarify: my approach was not to call any Fantom code in the web page, but instead, call the JavaScript generated by the relevant Fantom code.
(In the solution you are proposing, does it make sense to have an index.html file inside the main pod, and this index.html would make the appropriate references?)
Thanks for your patience :-)
andyMon 28 Jun 2010
Sounds like maybe you're confused about the role of WebMod - I'll try to catch up with you on IRC to explain it.
rfeldmanMon 28 Jun 2010
I am confused about this as well; after the IRC clarification, could I trouble you to post a summary of some sort on here?
andyMon 28 Jun 2010
@rfeldman - Depends on what you are confused about. I am guessing for both you, that it was the role WebMod plays. In this case, the Wisp server has just a single WebMod - so its responsible for every HTTP request coming in. So as ystrot pointed out, you need to follow the same design as js/demo and allow it to service requests for the external JavaScript scripts. dreire's example returns the index HTML for every request to his webserver. I believe the js/demo already does exactly what you want.
dfreireMon 28 Jun 2010
Thanks to ystrot and andy for correctly identifying the problem (which was of course, the onGet method always retrieving the same content, regardless of the call - silly me).
So an updated - and fully working - version looks like this:
using util
using web
using webmod
using wisp
class Demo : AbstractMain
{
@Opt { help = "http port" }
Int port := 8080
override Int run()
{
wisp := WispService
{
it.port = this.port
it.root = DemoMod()
}
return runServices([wisp])
}
}
const class DemoMod : WebMod
{
override Void onGet()
{
name := req.modRel.path.first
if (name == null)
onIndex // http://localhost:8080
else if (name == "pod")
onPodFile // http://localhost:8080/pod/helloJsStep3Demo/res/index.html
}
Void onIndex()
{
res.headers["Content-Type"] = "text/html; charset=utf-8"
res.out.docType
res.out.html
res.out.head
res.out.title.w("Demo").titleEnd
res.out.includeJs(`/pod/sys/sys.js`)
res.out.includeJs(`/pod/web/web.js`)
res.out.includeJs(`/pod/gfx/gfx.js`)
res.out.includeJs(`/pod/dom/dom.js`)
res.out.includeJs(`/pod/helloJsStep3/helloJsStep3.js`)
res.out.includeJs(`/pod/helloJsStep3Demo/helloJsStep3Demo.js`)
res.out.headEnd
res.out.body
res.out.script.w(getJs()).scriptEnd
res.out.bodyEnd
res.out.htmlEnd
}
Str getJs()
{
Str js := "var demo = fan.helloJsStep3Demo.JsLibWrapperDemo.make();\n"
js += "demo.run();\n"
return js
}
Void onPodFile()
{
File file := ("fan://" + req.uri[1..-1]).toUri.get
if (!file.exists) { res.sendErr(404); return }
FileWeblet(file).onService
}
}
This code exemplifies two possible solutions for my original problem:
either dynamically construct the html page, with the onIndex()
or publish an html page located inside the pod, with the onPodFile()
dfreire Sun 27 Jun 2010
I have an HTML file to test a web application composed of several Fantom generated JavaScript files. Everything runs fine.
Now I'm trying to do the same thing, but instead of using the HTML file, I want to dynamically load the generated JavaScript files, which are contained in the pods.
The closest example I have encountered is the js demo, but I don't completely understand it, and it seems overcomplicated to my purposes (I don't want to compile any Fantom code on the fly, I just want to use already generated JavaScript). So I've tried my luck simplifying things to something like this:
Now, this code doesn't run in the browser, because "fan is not defined" (according to firebug).
It is clear that the res.out.includeJs(...) lines are not fetching the js files from the pods. But if that is so, how come this works without problem in the js demo?
Is there any simple way to do what I need?
Thanks!
Yuri Strot Mon 28 Jun 2010
The problem is you construct index page for any request to server. When browser loading content of js file it hook the same DemoMod.onGet method and get index content instead of js file.
js demo handle this situation correctly:
dfreire Mon 28 Jun 2010
ystrot, thanks for the reply, but as far as I understand, that serves one static file of one pod, but it does not serve several static contents of several pods, as it would be done in an html file.
(Having a single index page for any request to server is not a problem for me at the moment.)
andy Mon 28 Jun 2010
dfreire - you actually have two problems. The first, as ystrot noted, you need to modify your DemoMod to serve up the pod js files. Once that is fixed you will see the second, which is you're trying to execute js before you have loaded the dependencies. If you plan to call any Fantom APIs in your webpage - you must do so in your onLoad callback to guareente you have everything you need.
dfreire Mon 28 Jun 2010
andy, thanks but I don't get it yet...
Using the FileWeblet, I can only serve the js files of one pod, right? What if (as it is my case) I want to serve js files spread from different pods?
What if (as it will be my case in the future) I also want to link to external js files?
To clarify: my approach was not to call any Fantom code in the web page, but instead, call the JavaScript generated by the relevant Fantom code.
(In the solution you are proposing, does it make sense to have an index.html file inside the main pod, and this index.html would make the appropriate references?)
Thanks for your patience :-)
andy Mon 28 Jun 2010
Sounds like maybe you're confused about the role of WebMod - I'll try to catch up with you on IRC to explain it.
rfeldman Mon 28 Jun 2010
I am confused about this as well; after the IRC clarification, could I trouble you to post a summary of some sort on here?
andy Mon 28 Jun 2010
@rfeldman - Depends on what you are confused about. I am guessing for both you, that it was the role WebMod plays. In this case, the Wisp server has just a single WebMod - so its responsible for every HTTP request coming in. So as ystrot pointed out, you need to follow the same design as
js/demo
and allow it to service requests for the external JavaScript scripts. dreire's example returns the index HTML for every request to his webserver. I believe thejs/demo
already does exactly what you want.dfreire Mon 28 Jun 2010
Thanks to ystrot and andy for correctly identifying the problem (which was of course, the onGet method always retrieving the same content, regardless of the call - silly me).
So an updated - and fully working - version looks like this:
This code exemplifies two possible solutions for my original problem:
I have added this as the Step3 of my ongoing step-by-step Fantom examples.
Thanks again :-)