[Checkins] SVN: Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/
first attempt at ajax based widget validation. still not
functioning by javascript expressions are rendered correctly
Paul Carduner
paulcarduner at gmail.com
Wed Jul 4 17:57:00 EDT 2007
Log message for revision 77437:
first attempt at ajax based widget validation. still not functioning by javascript expressions are rendered correctly
Changed:
U Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/interfaces.py
A Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.py
A Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.txt
U Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/tests.py
-=-
Modified: Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/interfaces.py
===================================================================
--- Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/interfaces.py 2007-07-04 21:15:33 UTC (rev 77436)
+++ Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/interfaces.py 2007-07-04 21:56:59 UTC (rev 77437)
@@ -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."""
Added: Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.py
===================================================================
--- Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.py (rev 0)
+++ Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.py 2007-07-04 21:56:59 UTC (rev 77437)
@@ -0,0 +1,97 @@
+import zope.interface
+import zope.component
+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, field, request):
+ self.form = form
+ self.field = field # z3c.form.field.Field instance!!!
+ self.request = request
+
+ def _ajaxURL(self):
+ widget = self.form.widgets[self.field.__name__]
+
+ # build js expression for extracting widget value
+ # XXX: Maybe we should adapt the widget to IJSValueExtractorRenderer?
+ valueString = '$("#%s").val()' % (widget.id, )
+
+ # build a js expression that joins valueString expression
+ queryString = '"?widget-id=%s&value=" + %s' % (widget.id, 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,
+ IField,
+ 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)
+
+ ValidationRenderer = None
+
+ def _validate(self):
+ widgetID = self.request.get('widget-id')
+ self.fields = self.fields.select(widgetID)
+ self.updateWidgets()
+ return self.widgets.extract()
+
+
+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].doc()
+ return u'' # all OK
+
Property changes on: Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.txt
===================================================================
--- Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.txt (rev 0)
+++ Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.txt 2007-07-04 21:56:59 UTC (rev 77437)
@@ -0,0 +1,42 @@
+==========================
+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
+
+ >>> 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);
+ })
Property changes on: Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/jsvalidator.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/tests.py
===================================================================
--- Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/tests.py 2007-07-04 21:15:33 UTC (rev 77436)
+++ Sandbox/pcardune/z3cFormJS/trunk/src/z3c/formjs/tests.py 2007-07-04 21:56:59 UTC (rev 77437)
@@ -16,6 +16,11 @@
optionflags=zope.testing.doctest.NORMALIZE_WHITESPACE |
zope.testing.doctest.ELLIPSIS),
zope.testing.doctest.DocFileSuite(
+ 'jsvalidator.txt',
+ setUp=testing.setUp, tearDown=testing.tearDown,
+ optionflags=zope.testing.doctest.NORMALIZE_WHITESPACE |
+ zope.testing.doctest.ELLIPSIS),
+ zope.testing.doctest.DocFileSuite(
'jsbutton.txt',
setUp=testing.setUp, tearDown=testing.tearDown,
optionflags=zope.testing.doctest.NORMALIZE_WHITESPACE |
More information about the Checkins
mailing list