JavaScript Functions

When developing JavaScript-enabled user interfaces, it is often necessary to create small callback functions. The usual way of creating those functions is to write and register a resource, then create a viewlet for it that integrates it. Those steps can be tedious when writing small functions. Thus, this package provides a way to convert a Python method to a Javascript function.

>>> from z3c.formjs import jsfunction

So let’s create a simple view with a JavaScript function in it:

>>> class View(object):
...
...     @jsfunction.function('hw')
...     def showHelloWorldMessage(self):
...         return u"alert('Hello World!');"

The argument to jsfunction.function is the namspace into which the function will be placed. This argument is optional. The Python method is expected to return the Javascript code as a string. All functions are collected in a special attribute called “jsFunctions”

>>> View.jsFunctions
<JSFunctions
    {'hw': [<JSFunction showHelloWorldMessage>]}>

The functions can be rendered directly:

>>> print View.jsFunctions.render()
var hw = {
  showHelloWorldMessage: function() {
    alert('Hello World!');
  }
}

Similarly to Javascript subscriptions, a JavaScript viewlet exists for any view containing JavaScript functions that provides the following output:

>>> viewlet = jsfunction.JSFunctionsViewlet(
...     object(), object(), View(), object())
>>> viewlet.update()
>>> print viewlet.render()
<script type="text/javascript">
  var hw = {
    showHelloWorldMessage: function() {
      alert('Hello World!');
    }
  }
</script>

Let’s now have a closer look at the decorator. As mentioned before, the namespace is optional. So what happens if the namespace is not specified? Then the function should be declared normally:

>>> class View(object):
...
...     @jsfunction.function()
...     def showHelloWorldMessage(self):
...         return u"alert('Hello World!');"
>>> print View.jsFunctions.render()
function showHelloWorldMessage() {
  alert('Hello World!');
}

Of course you can mix namespace and non-namespace functions:

>>> class View(object):
...
...     @jsfunction.function()
...     def show1(self):
...         return u"alert('Hello World!');"
...
...     @jsfunction.function('ns1')
...     def show1(self):
...         return u"alert('Hello World!');"
...
...     @jsfunction.function('ns1')
...     def show2(self):
...         return u"alert('Hello World!');"
>>> print View.jsFunctions.render()
function show1() {
  alert('Hello World!');
}
var ns1 = {
  show1: function() {
    alert('Hello World!');
  },
  show2: function() {
    alert('Hello World!');
  }
}

What about arguments? The arguments are directly extracted into the code. Currently, keyword arguments, and variable positional and keyword arguments are not supported, as they are not supported by JavaScript either:

>>> class View(object):
...
...     @jsfunction.function('ns')
...     def show(self, title):
...         return u"alert('Title' + title);"
>>> print View.jsFunctions.render()
var ns = {
  show: function(title) {
    alert('Title' + title);
  }
}

And that is realy everything that there is to it.

Calling JSFunctions from Python

We can also render a JavaScript call to a JSFunction from within python using the call method of the function. We can even pass the call method the arguments to be rendered.

>>> View.show.call(u"Some Title")
"ns.show('Some Title');"
>>> View.show.call("Some Title")
"ns.show('Some Title');"
>>> View.show.call(3.0)
'ns.show(3.0);'
>>> View.show.call(1)
'ns.show(1);'
>>> View.show.call(True)
'ns.show(true);'

Unsupported data types are just rendered as stritree/ngs.

>>> View.show.call(object())
"ns.show('<object object at ...>');"

Functions without namespaces also render correctly:

>>> class View(object):
...
...     @jsfunction.function()
...     def show(self, title):
...         return u"alert('Title' + title);"
>>> View.show.call(u"Some Title")
"show('Some Title');"

Table Of Contents

Previous topic

Connecting to Javascript Events

Next topic

AJAX Helpers

This Page