[Checkins] SVN: z3c.formjs/trunk/s I needed to do some changes to
get the JS Validator demo working.
Stephan Richter
srichter at cosmos.phy.tufts.edu
Thu Jul 5 12:41:06 EDT 2007
Log message for revision 77473:
I needed to do some changes to get the JS Validator demo working.
Changed:
U z3c.formjs/trunk/setup.py
U z3c.formjs/trunk/src/z3c/formjs/interfaces.py
A z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py
A z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt
-=-
Modified: z3c.formjs/trunk/setup.py
===================================================================
--- z3c.formjs/trunk/setup.py 2007-07-05 16:40:24 UTC (rev 77472)
+++ z3c.formjs/trunk/setup.py 2007-07-05 16:41:06 UTC (rev 77473)
@@ -71,6 +71,7 @@
'setuptools',
'z3c.form',
'z3c.formui',
+ 'z3c.traverser',
'zope.app.pagetemplate',
'zope.component',
'zope.interface',
Modified: z3c.formjs/trunk/src/z3c/formjs/interfaces.py
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/interfaces.py 2007-07-05 16:40:24 UTC (rev 77472)
+++ z3c.formjs/trunk/src/z3c/formjs/interfaces.py 2007-07-05 16:41:06 UTC (rev 77473)
@@ -124,3 +124,24 @@
def update():
"""Setup actions."""
+
+
+class IAJAXValidator(Interface):
+ """A validator that sends back validation data sent from an ajax request."""
+
+ ValidationRenderer = schema.Object(
+ schema=Interface,
+ title=u"Validation Renderer")
+
+ def validate():
+ """return validation data."""
+
+
+class IJSMessageValidationRenderer(Interface):
+ """renders a js expression for sending/processing ajax validation requests."""
+
+ def __init__(form, field, request):
+ """store the form field and request, because this adapts those items."""
+
+ def render():
+ """Render the js expression."""
Copied: z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py (from rev 77470, Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.py)
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py (rev 0)
+++ z3c.formjs/trunk/src/z3c/formjs/jsvalidator.py 2007-07-05 16:41:06 UTC (rev 77473)
@@ -0,0 +1,110 @@
+import zope.interface
+import zope.component
+
+from z3c.traverser.traverser import SingleAttributeTraverserPlugin
+from z3c.traverser.interfaces import IPluggableTraverser, ITraverserPlugin
+from z3c.form.interfaces import IWidget, IField
+
+from jquery.layer import IJQueryJavaScriptBrowserLayer
+
+from z3c.formjs import interfaces
+
+
+## @zope.component.adapter(IWidget, IJQueryJavaScriptBrowserLayer)
+## @zope.interface.implementer(interfaces.IJSErrorMessageRenderer)
+## def JQueryErrorMessageRenderer(widgetID):
+## return '''$.get()'''
+
+
+class JQueryBaseValidationRenderer(object):
+
+ def __init__(self, form, widgetID, request):
+ self.form = form
+ self.widgetID = widgetID
+ self.request = request
+
+ def _ajaxURL(self):
+ # build js expression for extracting widget value
+ # XXX: Maybe we should adapt the widget to IJSValueExtractorRenderer?
+ valueString = '$("#%s").val()' % self.widgetID
+
+ # build a js expression that joins valueString expression
+ queryString = '"?widget-id=%s&%s=" + %s' % (self.widgetID, self.widgetID.replace('-','.'), valueString)
+
+ # build a js expression that joins form url, validate path, and query string
+ ajaxURL = '"'+self.form.request.getURL() + '/validate" + ' + queryString
+
+ # it should look something like this now:
+ # "path/to/form.html/validate" + "?widget-id=some-id&value=" + $("#some-id").val()
+ return ajaxURL
+
+
+class JQueryMessageValidationRenderer(JQueryBaseValidationRenderer):
+
+ zope.interface.implements(interfaces.IJSMessageValidationRenderer)
+ zope.component.adapts(interfaces.IAJAXValidator,
+ zope.interface.Interface,
+ IJQueryJavaScriptBrowserLayer)
+
+ def render(self):
+ ajaxURL = self._ajaxURL()
+ # build a js expression that shows the user the error message
+ # XXX: later this should query for a renderer based on the widget
+ # jsrenderer = zope.component.queryMultiAdapter(
+ # (widget, self.request), interfaces.IJSErrorMessageRenderer)
+ # messageSetter = jsrenderer.render()
+ messageSetter = 'alert(data);'
+ ajax = '$.get(%s,\nfunction(data){\n%s\n})' % (ajaxURL, messageSetter)
+ return ajax
+
+
+class MessageValidationRenderer(object):
+ """An intermediate class that performs adapter look ups.
+
+ This way you don't have to do as many adapter look ups in your Form class.
+ """
+
+ def __init__(self, form, field):
+ self.form = form
+ self.field = field
+
+ def render(self):
+ jsrenderer = zope.component.queryMultiAdapter(
+ (self.form, self.field, self.form.request), interfaces.IJSMessageValidationRenderer)
+ return jsrenderer.render()
+
+
+class BaseValidator(object):
+ zope.interface.implements(interfaces.IAJAXValidator,
+ IPluggableTraverser)
+
+ ValidationRenderer = None
+
+ def _validate(self):
+ widgetID = self.request.get('widget-id')
+ fieldName = widgetID.replace('form-widgets-','')
+ self.fields = self.fields.select(fieldName)
+ self.updateWidgets()
+ return self.widgets.extract()
+
+ def publishTraverse(self, request, name):
+ # 1. Look at all the traverser plugins, whether they have an answer.
+ for traverser in zope.component.subscribers((self, request),
+ ITraverserPlugin):
+ try:
+ return traverser.publishTraverse(request, name)
+ except NotFound:
+ pass
+
+
+class MessageValidator(BaseValidator):
+ '''Validator that sends error messages for widget in questiodn.'''
+ ValidationRenderer = MessageValidationRenderer
+
+ def validate(self):
+ data, errors = self._validate()
+ if errors:
+ return errors[0].message
+ return u'' # all OK
+
+ValidateTraverser = SingleAttributeTraverserPlugin('validate')
Copied: z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt (from rev 77470, Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.txt)
===================================================================
--- z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt (rev 0)
+++ z3c.formjs/trunk/src/z3c/formjs/jsvalidator.txt 2007-07-05 16:41:06 UTC (rev 77473)
@@ -0,0 +1,63 @@
+==========================
+JavaScript Form Validation
+==========================
+
+Server-side validation via AJAX
+
+Message Validator
+-----------------
+
+This validator returns an error message for a given widget.
+
+ >>> from z3c.formjs import interfaces as jsinterfaces
+ >>> from z3c.formjs import jsvalidator, jsevent
+ >>> from z3c.form import form, field, interfaces
+
+ >>> from z3c.form.testing import setupFormDefaults
+ >>> setupFormDefaults()
+
+ >>> import zope.interface
+ >>> import zope.schema
+ >>> class IAddress(zope.interface.Interface):
+ ... zip = zope.schema.Int(title=u"Zip Code")
+
+
+ >>> class AddressEditForm(jsvalidator.MessageValidator, form.AddForm):
+ ... fields = field.Fields(IAddress)
+ ...
+ ... @jsevent.handler(interfaces.IField, event=jsevent.CHANGE)
+ ... def fieldValidator(self, field):
+ ... return self.ValidationRenderer(self, field).render()
+
+ >>> from z3c.formjs.testing import TestRequest
+ >>> request = TestRequest()
+ >>> edit = AddressEditForm(None, request)
+ >>> edit.update()
+
+We will register a jquery renderer.
+
+ >>> import zope.component
+ >>> zope.component.provideAdapter(jsvalidator.JQueryMessageValidationRenderer)
+ >>> print edit.fieldValidator(edit, edit.fields['zip'])
+ $.get("http://127.0.0.1/validate" + "?widget-id=form-widgets-zip&value=" + $("#form-widgets-zip").val(),
+ function(data){
+ alert(data);
+ })
+
+ >>> from zope.publisher.interfaces import IPublisherRequest
+ >>> from z3c.traverser import traverser
+ >>> zope.component.provideSubscriptionAdapter(traverser.AttributeTraverserPlugin,
+ ... (jsinterfaces.IAJAXValidator, IPublisherRequest))
+ >>> from z3c.traverser.traverser import PluggableTraverser
+ >>> request = TestRequest(form={'widget-id':'form-widgets-zip',
+ ... 'form.widgets.zip':'29132'})
+ >>> edit = AddressEditForm(None, request)
+ >>> edit.update()
+ >>> PluggableTraverser(edit, request).publishTraverse(request, 'validate')()
+ u''
+ >>> request = TestRequest(form={'widget-id':'form-widgets-zip',
+ ... 'form.widgets.zip':'notazipcode'})
+ >>> edit = AddressEditForm(None, request)
+ >>> edit.update()
+ >>> PluggableTraverser(edit, request).publishTraverse(request, 'validate')()
+ u''
\ No newline at end of file
More information about the Checkins
mailing list