[Checkins] SVN: z3c.formjs/trunk/src/z3c/formjs/ Hopefully this makes this package 100% tested.

Stephan Richter srichter at cosmos.phy.tufts.edu
Sun Jul 8 01:50:09 EDT 2007


Log message for revision 77602:
  Hopefully this makes this package 100% tested.
  

Changed:
  U   z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.py
  U   z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.txt
  U   z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py
  U   z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt
  U   z3c.formjs/trunk/src/z3c/formjs/testing.py

-=-
Modified: z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.py
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.py	2007-07-08 03:44:34 UTC (rev 77601)
+++ z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.py	2007-07-08 05:50:09 UTC (rev 77602)
@@ -106,7 +106,10 @@
 
         return ajaxURL
 
+    def update(self):
+        pass
 
+
 class JQueryMessageValidationScriptRenderer(JQueryBaseValidationScriptRenderer):
     zope.component.adapts(
         interfaces.IMessageValidationScript, IJQueryJavaScriptBrowserLayer)

Modified: z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.txt
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.txt	2007-07-08 03:44:34 UTC (rev 77601)
+++ z3c.formjs/trunk/src/z3c/formjs/jqueryrenderer.txt	2007-07-08 05:50:09 UTC (rev 77602)
@@ -90,3 +90,42 @@
     $("#form-id").bind("click", function(event){alert("Here!");});
     $("#form-id").bind("dblclick", function(event){alert("Here!");});
   })
+
+``IMessageValidationScript`` Renderer
+-------------------------------------
+
+This renderer defines how the Javascript defines the validation on the client
+side. It must extract the data from the DOM tree, send it to the server for
+validation, accept the return message and integrate it in the DOM tree.
+
+So let's create the message validation script:
+
+  >>> from z3c.form.form import Form
+  >>> form = Form(None, request)
+
+  >>> from z3c.form.widget import Widget
+  >>> widget = Widget(request)
+  >>> widget.id = 'form-zip'
+  >>> widget.name = 'form.zip'
+  >>> widget.__name__ = 'zip'
+
+  >>> from z3c.formjs import jsvalidator
+  >>> script = jsvalidator.MessageValidationScript(form, widget)
+
+Let's now register the renderer:
+
+  >>> import zope.component
+  >>> zope.component.provideAdapter(
+  ...     jqueryrenderer.JQueryMessageValidationScriptRenderer)
+
+Now we can render the script:
+
+  >>> renderer = zope.component.getMultiAdapter(
+  ...     (script, request), interfaces.IRenderer)
+  >>> renderer.update()
+  >>> print renderer.render()
+  $.get("http://127.0.0.1/validate" +
+            "?widget-name=zip&form.zip=" + $("#form-zip").val(),
+        function(data){
+            if (data != "") { alert(data); }
+        })

Modified: z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py	2007-07-08 03:44:34 UTC (rev 77601)
+++ z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py	2007-07-08 05:50:09 UTC (rev 77602)
@@ -18,6 +18,7 @@
 __docformat__ = "reStructuredText"
 import zope.interface
 import zope.component
+from zope.publisher.interfaces import NotFound
 
 from z3c.traverser.traverser import SingleAttributeTraverserPlugin
 from z3c.traverser.interfaces import IPluggableTraverser, ITraverserPlugin
@@ -49,7 +50,9 @@
             except NotFound:
                 pass
 
+        raise NotFound(self.context, name, request)
 
+
 class MessageValidationScript(object):
     zope.interface.implements(interfaces.IMessageValidationScript)
 
@@ -58,7 +61,7 @@
         self.widget = widget
 
     def render(self):
-        renderer = zope.component.queryMultiAdapter(
+        renderer = zope.component.getMultiAdapter(
             (self, self.form.request), interfaces.IRenderer)
         return renderer.render()
 

Modified: z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt	2007-07-08 03:44:34 UTC (rev 77601)
+++ z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt	2007-07-08 05:50:09 UTC (rev 77602)
@@ -2,80 +2,107 @@
 JavaScript Form Validation
 ==========================
 
-Server-side validation via AJAX
+This package also supports widget value validation via Javascript. In
+particular, the ``jsvalidator`` module implements server-side validation via
+AJAX.
 
+  >>> from z3c.formjs import jsvalidator
+
+There are two components to the validation API. The first is the validator, a
+form mix-in class that makes the validation functionality via a URL and
+defines the communication protocol of the validation; for example, it defines
+what path must be accessed for the validation and what data to send and
+return. The second component is the validation script, which is responsible
+for defining the Javascript code that is executed when validation is
+requested.
+
+
 Message Validator
 -----------------
 
-This validator returns an error message for a given widget.
+The goal of the specific message validator is to validate a value, then
+convert any error into a message and insert the message into the page's
+content.
 
-    >>> from z3c.formjs import interfaces as jsinterfaces
-    >>> from z3c.formjs import jsvalidator, jsevent, jsaction
-    >>> from z3c.form import form, field, interfaces
+So let's do some necessary setups:
 
-    >>> from z3c.form.testing import setupFormDefaults
-    >>> setupFormDefaults()
 
-    >>> import zope.component
-    >>> from z3c.form import error
-    >>> zope.component.provideAdapter(error.ValueErrorViewSnippet)
+  >>> from z3c.form.testing import setupFormDefaults
+  >>> setupFormDefaults()
 
+  >>> import zope.component
+  >>> from z3c.form import error
+  >>> zope.component.provideAdapter(error.ValueErrorViewSnippet)
 
-    >>> import zope.interface
-    >>> import zope.schema
-    >>> class IAddress(zope.interface.Interface):
-    ...     zip = zope.schema.Int(title=u"Zip Code")
+We now create a simple form in which all widgets will be validated:
 
+  >>> import zope.interface
+  >>> import zope.schema
 
-    >>> class AddressEditForm(jsvalidator.MessageValidator, form.AddForm):
-    ...     fields = field.Fields(IAddress)
-    ...
-    ...     @jsaction.handler(interfaces.IField, event=jsevent.CHANGE)
-    ...     def fieldValidator(self, event, selector):
-    ...         return self.ValidationScript(self, selector.widget).render()
+  >>> class IAddress(zope.interface.Interface):
+  ...     zip = zope.schema.Int(title=u"Zip Code")
 
-    >>> from z3c.form.testing import TestRequest
-    >>> request = TestRequest()
-    >>> from jquery.layer import IJQueryJavaScriptBrowserLayer
-    >>> import zope.interface
-    >>> zope.interface.alsoProvides(request, IJQueryJavaScriptBrowserLayer)
+  >>> from z3c.form import form, field
+  >>> from z3c.form.interfaces import IField
+  >>> from z3c.formjs import jsevent, jsaction
 
-    >>> edit = AddressEditForm(None, request)
-    >>> edit.update()
+  >>> class AddressEditForm(jsvalidator.MessageValidator, form.AddForm):
+  ...     fields = field.Fields(IAddress)
+  ...
+  ...     @jsaction.handler(IField, event=jsevent.CHANGE)
+  ...     def fieldValidator(self, event, selector):
+  ...         return self.ValidationScript(self, selector.widget).render()
 
-We will register a jquery renderer.
+After instantiating the form, ...
 
-    >>> import zope.component
-    >>> from z3c.formjs import jqueryrenderer
-    >>> zope.component.provideAdapter(
-    ...     jqueryrenderer.JQueryMessageValidationScriptRenderer)
+  >>> from z3c.form.testing import TestRequest
+  >>> request = TestRequest()
+  >>> edit = AddressEditForm(None, request)
+  >>> edit.update()
 
-    >>> print edit.fieldValidator(
-    ...     None, jsaction.WidgetSelector(edit.widgets['zip']), request)
-    $.get("http://127.0.0.1/validate" +
-          "?widget-name=zip&form.widgets.zip=" +
-          $("#form-widgets-zip").val(),
-          function(data){
-              if (data != "") { alert(data); }
-          })
+we can execute the handler to ensure we get some output:
 
-    >>> from zope.publisher.interfaces import IPublisherRequest
-    >>> from z3c.traverser import traverser
-    >>> zope.component.provideSubscriptionAdapter(
-    ...     traverser.AttributeTraverserPlugin,
-    ...     (jsinterfaces.IAJAXValidator, IPublisherRequest))
+  >>> from z3c.formjs import testing
+  >>> testing.setupRenderers()
 
-    >>> from z3c.traverser.traverser import PluggableTraverser
-    >>> request = TestRequest(form={'widget-name' : 'zip',
-    ...                             'form.widgets.zip' : u'29132'})
-    >>> edit = AddressEditForm(None, request)
-    >>> edit.update()
-    >>> PluggableTraverser(edit, request).publishTraverse(request, 'validate')()
-    u''
+  >>> from z3c.formjs import jsaction
+  >>> print edit.fieldValidator(
+  ...     None, jsaction.WidgetSelector(edit.widgets['zip']), request)
+  $.get('/validate', function(data){ alert(data) })
 
-    >>> request = TestRequest(form={'widget-name': 'zip',
-    ...                             'form.widgets.zip':'notazipcode'})
-    >>> edit = AddressEditForm(None, request)
-    >>> edit.update()
-    >>> PluggableTraverser(edit, request).publishTraverse(request, 'validate')()
-    u'The system could not process the given value.'
+Validators also support pluggable traverser plugins. So once we register the
+``validate`` traverser for any validator, ...
+
+  >>> from z3c.formjs import interfaces
+  >>> zope.component.provideSubscriptionAdapter(
+  ...     jsvalidator.ValidateTraverser,
+  ...     (interfaces.IAJAXValidator, TestRequest) )
+
+we can traverse to the ``validate`` method and render it. Let's first render
+some valid input:
+
+  >>> request = TestRequest(form={'widget-name' : 'zip',
+  ...                             'form.widgets.zip' : u'29132'})
+  >>> edit = AddressEditForm(None, request)
+  >>> edit.update()
+  >>> edit.publishTraverse(request, 'validate')()
+  u''
+
+As you can see there is no error message. Let's now provide an invalid ZIP
+code. As you can see, we get the expected error message:
+
+  >>> request = TestRequest(form={'widget-name': 'zip',
+  ...                             'form.widgets.zip':'notazipcode'})
+  >>> edit = AddressEditForm(None, request)
+  >>> edit.update()
+  >>> edit.publishTraverse(request, 'validate')()
+  u'The system could not process the given value.'
+
+Of course, one cannot just traverse to any attribute in the form:
+
+  >>> edit.publishTraverse(request, 'ValidationScript')
+  Traceback (most recent call last):
+  ...
+  NotFound: Object: None, name: 'ValidationScript'
+
+And that's it.

Modified: z3c.formjs/trunk/src/z3c/formjs/testing.py
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/testing.py	2007-07-08 03:44:34 UTC (rev 77601)
+++ z3c.formjs/trunk/src/z3c/formjs/testing.py	2007-07-08 05:50:09 UTC (rev 77602)
@@ -82,10 +82,24 @@
             '\n  '.join([r.render() for r in self.renderers]) )
 
 
+class MessageValidationScriptRenderer(object):
+    zope.interface.implements(interfaces.IRenderer)
+    zope.component.adapts(
+        interfaces.IMessageValidationScript, IBrowserRequest)
+
+    def __init__(self, script, request):
+        self.script = script
+        self.request = request
+
+    def render(self):
+        return "$.get('/validate', function(data){ alert(data) })"
+
+
 def setupRenderers():
     zope.component.provideAdapter(IdSelectorRenderer)
     zope.component.provideAdapter(SubscriptionRenderer)
     zope.component.provideAdapter(ManagerRenderer)
+    zope.component.provideAdapter(MessageValidationScriptRenderer)
 
 
 def addTemplate(form, filename):



More information about the Checkins mailing list