[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