[Checkins] SVN: z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction. redo the way functions are rendered so we can support nested namespaces.

Paul Carduner paulcarduner at gmail.com
Fri Jul 11 23:32:33 EDT 2008


Log message for revision 88274:
  redo the way functions are rendered so we can support nested namespaces.

Changed:
  U   z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.py
  U   z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.txt

-=-
Modified: z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.py
===================================================================
--- z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.py	2008-07-12 01:48:39 UTC (rev 88273)
+++ z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.py	2008-07-12 03:32:31 UTC (rev 88274)
@@ -77,34 +77,43 @@
         self._functions = {}
 
     def add(self, jsFunction, namespace=''):
-        ns = self._functions.setdefault(namespace, [])
-        ns.append(jsFunction)
+        ns = self._functions.setdefault(namespace, {})
+        ns[jsFunction.name] = jsFunction
         return jsFunction
 
     def render(self):
         result = ''
         # Render non-namespaced functions
-        for func in self._functions.get('', []):
+        for func in self._functions.get('', {}).values():
             args = func.arguments
-            result += 'function %s(%s) {\n' %(
+            result += 'var %s = function (%s) {\n' %(
                 func.name, ', '.join(args) )
             code = func.render()
             result += '  ' + code.replace('\n', '\n  ') + '\n'
             result += '}\n'
-        # Render namespaced functions
+
+        # initialize namespaces
+        rendered = []
+        for nsIndex, ns in enumerate(sorted(self._functions.keys())):
+            if ns and nsIndex == 0:
+                result += 'var '
+            parts = ns.split('.')
+            for index in xrange(len(ns)):
+                path = '.'.join(parts[:index+1])
+                if path not in rendered:
+                    result += '%s = {};\n' % path
+                    rendered.append(path)
+
         for ns, funcs in self._functions.items():
             if ns == '':
                 continue
-            result += 'var %s = {\n' %ns
-            for func in funcs:
+            for func in funcs.values():
                 args = func.arguments
-                result += '  %s: function(%s) {\n' %(
-                    func.name, ', '.join(args) )
+                result += '%s.%s = function(%s) {\n' %(
+                    ns, func.name, ', '.join(args) )
                 code = func.render()
-                result += '    ' + code.replace('\n', '\n    ') + '\n'
-                result += '  },\n'
-            result = result[:-2] + '\n'
-            result += '}\n'
+                result += '  ' + code.replace('\n', '\n  ') + '\n'
+                result += '};\n'
         return result
 
     def __repr__(self):

Modified: z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.txt
===================================================================
--- z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.txt	2008-07-12 01:48:39 UTC (rev 88273)
+++ z3c.formjs/branches/pcardune-client-notify-r87806/src/z3c/formjs/jsfunction.txt	2008-07-12 03:32:31 UTC (rev 88274)
@@ -25,17 +25,74 @@
 
   >>> View.jsFunctions
   <JSFunctions
-      {'hw': [<JSFunction showHelloWorldMessage>]}>
+      {'hw': {'showHelloWorldMessage': <JSFunction showHelloWorldMessage>}}>
 
 The functions can be rendered directly:
 
   >>> print View.jsFunctions.render()
-  var hw = {
-    showHelloWorldMessage: function() {
-      alert('Hello World!');
-    }
-  }
+  var hw = {};
+  hw.showHelloWorldMessage = function() {
+    alert('Hello World!');
+  };
 
+We can also give a dotted path for the namespace, which will in turn
+be reflect in javascript:
+
+  >>> class View(object):
+  ...
+  ...     @jsfunction.function('z3c.formjs.hw')
+  ...     def showHelloWorldMessage(self):
+  ...         return u"alert('Hello World!');"
+
+  >>> View.jsFunctions
+  <JSFunctions {'z3c.formjs.hw':
+        {'showHelloWorldMessage': <JSFunction showHelloWorldMessage>}}>
+
+  >>> print View.jsFunctions.render()
+  var z3c = {};
+  z3c.formjs = {};
+  z3c.formjs.hw = {};
+  z3c.formjs.hw.showHelloWorldMessage = function() {
+    alert('Hello World!');
+  };
+
+We can also do mixed level namespacing:
+
+  >>> class View(object):
+  ...
+  ...     @jsfunction.function('z3c.formjs.hw')
+  ...     def foo(self):
+  ...         return u"alert('Foo');"
+  ...
+  ...     @jsfunction.function('z3c.formjs')
+  ...     def bar(self):
+  ...         return u"alert('Bar');"
+  ...
+  ...     @jsfunction.function('z3c.formjs.hw')
+  ...     def baz(self):
+  ...         return u"alert('Baz');"
+
+  >>> View.jsFunctions
+  <JSFunctions {'z3c.formjs.hw': {'foo': <JSFunction foo>,
+                                  'baz': <JSFunction baz>},
+                'z3c.formjs': {'bar': <JSFunction bar>}}>
+
+  >>> print View.jsFunctions.render()
+  var z3c = {};
+  z3c.formjs = {};
+  z3c.formjs.hw = {};
+  z3c.formjs.hw.foo = function() {
+    alert('Foo');
+  };
+  z3c.formjs.hw.baz = function() {
+    alert('Baz');
+  };
+  z3c.formjs.bar = function() {
+    alert('Bar');
+  };
+
+
+
 Similarly to Javascript subscriptions, a JavaScript viewlet exists for
 any view containing JavaScript functions that provides the following
 output:
@@ -45,13 +102,23 @@
   >>> viewlet.update()
   >>> print viewlet.render()
   <script type="text/javascript">
-    var hw = {
-      showHelloWorldMessage: function() {
-        alert('Hello World!');
-      }
-    }
+    var z3c = {};
+    z3c.formjs = {};
+    z3c.formjs.hw = {};
+    z3c.formjs.hw.foo = function() {
+      alert('Foo');
+    };
+    z3c.formjs.hw.baz = function() {
+      alert('Baz');
+    };
+    z3c.formjs.bar = function() {
+      alert('Bar');
+    };
   </script>
 
+!Note! a form must implement IHaveJSFunctions for the viewlet to be
+rendered.
+
 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:
@@ -63,7 +130,7 @@
   ...         return u"alert('Hello World!');"
 
   >>> print View.jsFunctions.render()
-  function showHelloWorldMessage() {
+  var showHelloWorldMessage = function () {
     alert('Hello World!');
   }
 
@@ -84,17 +151,16 @@
   ...         return u"alert('Hello World!');"
 
   >>> print View.jsFunctions.render()
-  function show1() {
+  var show1 = function () {
     alert('Hello World!');
   }
-  var ns1 = {
-    show1: function() {
-      alert('Hello World!');
-    },
-    show2: function() {
-      alert('Hello World!');
-    }
-  }
+  ns1 = {};
+  ns1.show1 = function() {
+    alert('Hello World!');
+  };
+  ns1.show2 = function() {
+    alert('Hello World!');
+  };
 
 What about arguments? The arguments are directly extracted into the
 code. Currently, keyword arguments, and variable positional and keyword
@@ -107,13 +173,12 @@
   ...         return u"alert('Title' + title);"
 
   >>> print View.jsFunctions.render()
-  var ns = {
-    show: function(title) {
-      alert('Title' + title);
-    }
-  }
+  var ns = {};
+  ns.show = function(title) {
+    alert('Title' + title);
+  };
 
-And that is realy everything that there is to it.
+And that is really everything that there is to it.
 
 
 Calling JSFunctions from Python
@@ -134,7 +199,7 @@
   >>> View.show.call(True)
   'ns.show(true);'
 
-Unsupported data types are just rendered as stritree/ngs.
+Unsupported data types are just rendered as strings.
 
   >>> View.show.call(object())
   "ns.show('<object object at ...>');"



More information about the Checkins mailing list