Divmod : Nevow
Athena
LiveElement Tutorial
Subclass nevow.athena.LiveElement and provide a docFactory which uses the liveElement renderer:
from nevow import athena, loaders, tags as T class MyElement(athena.LiveElement): docFactory = loaders.stan(T.div(render=T.directive('liveElement')))
Put the result onto a nevow.athena.LivePage somehow:
class MyPage(athena.LivePage): docFactory = loaders.stan(T.html[ T.head(render=T.directive('liveglue')), T.body(render=T.directive('myElement'))]) def render_myElement(self, ctx, data): f = MyElement() f.setFragmentParent(self) return ctx.tag[f] def child_(self, ctx): return MyPage()
Put the page into a nevow.appserver.NevowSite somehow:
from nevow import appserver site = appserver.NevowSite(MyPage())
Hook the site up to the internet:
from twisted.application import service, internet application = service.Application("Athena Demo") webService = internet.TCPServer(8080, site) webService.setServiceParent(application)
Put it all into a .tac file and run it:
twistd -noy myelement.tac
And hit <http://localhost:8080/>. You now have an extremely simple Athena page.
Customizing Behavior
Add a Twisted plugin which maps your module name onto your JavaScript source file:
from nevow import athena myPackage = athena.JSPackage({ 'MyModule': '/absolute/path/to/mymodule.js', })
Place this Python source file into nevow/plugins/ (the Twisted plugin documentation describes where else you can put it, with the exception that Nevow plugins should be placed beneath a nevow directory as opposed to a twisted directory).
In the JavaScript source file (in this case, mymodule.js), import Nevow.Athena:
// import Nevow.Athena
Next, subclass the JavaScript Nevow.Athena.Widget class (notice the module name that was defined in the plugin file):
MyModule.MyWidget = Nevow.Athena.Widget.subclass('MyModule.MyWidget');
Now, add a method to your newly defined class:
MyModule.MyWidget.methods(
function echo(self, argument) {
alert("Echoing " + argument);
return argument;
});
Define the JavaScript class which will correspond to your LiveElement subclass:
from nevow import athena, loaders, tags as T class MyElement(athena.LiveElement): jsClass = u'MyModule.MyWidget' docFactory = loaders.stan(T.div(render=T.directive('liveElement')))
Invoking Code in the Browser
Add some kind of event source (in this case, a timer, but this is incidental) which will cause the server to call a method in the browser:
from twisted.internet import reactor from nevow import athena, loaders, tags as T class MyElement(athena.LiveElement): jsClass = u'MyModule.MyWidget' docFactory = loaders.stan(T.div(render=T.directive('liveElement'))) def __init__(self, *a, **kw): super(MyElement, self).__init__(*a, **kw) reactor.callLater(5, self.myEvent) def myEvent(self): print 'My Event Firing' self.callRemote('echo', 12345)
Start up the server again and revisit <http://localhost:8080>.
Invoking Code on the Server
Add an event source (in this case, a user-interface element, but this is incidental) which will cause the browser to call a method on the server:
class MyElement(athena.LiveElement): docFactory = loaders.stan(T.div(render=T.directive('liveElement'))[ T.input(type="submit", value="Push me", onclick='Nevow.Athena.Widget.get(this).clicked()')]) ...
Update the JavaScript definition of MyModule.MyWidget to handle this event and actually call the server method:
MyModule.MyWidget.method(
'clicked',
function(self) {
self.callRemote('echo', 'hello, world');
});
Add a method to MyElement which the browser will call, and expose it to the browser:
class MyElement(athena.LiveElement): ... def echo(self, argument): print 'Echoing', argument return argument athena.expose(echo)
Start up the server again and revisit <http://localhost:8080>.
