The jqueryrenderer module implements the backend javascript code using the JQuery Javascript library. All renderers assume that JQuery has been loaded.
>>> from z3c.formjs import interfaces, jqueryrenderer
JQuery uses CSS-selector syntax to select DOM elements. This makes the id selector renderer a very simple component:
>>> from z3c.formjs import jsevent >>> selector = jsevent.IdSelector('form-id')>>> from z3c.form.testing import TestRequest >>> request = TestRequest()>>> from jquery.layer import IJQueryJavaScriptBrowserLayer >>> import zope.interface >>> zope.interface.alsoProvides(request, IJQueryJavaScriptBrowserLayer)
Let’s now register the renderer:
>>> import zope.component
>>> zope.component.provideAdapter(jqueryrenderer.JQueryIdSelectorRenderer)
Like any view component, the renderer must be updated before being rendered:
>>> renderer = zope.component.getMultiAdapter(
... (selector, request), interfaces.IRenderer)
>>> renderer.update()
>>> print renderer.render()
#form-id
Since JQuery uses CSS selectors, we can simply pass through the CSS expression:
>>> from z3c.formjs import jsevent >>> cssSelector = jsevent.CSSSelector('label')>>> from z3c.form.testing import TestRequest >>> request = TestRequest()>>> from jquery.layer import IJQueryJavaScriptBrowserLayer >>> import zope.interface >>> zope.interface.alsoProvides(request, IJQueryJavaScriptBrowserLayer)
Let’s now register the renderer:
>>> import zope.component
>>> zope.component.provideAdapter(jqueryrenderer.JQueryCSSSelectorRenderer)
Like any view component, the renderer must be updated before being rendered:
>>> renderer = zope.component.getMultiAdapter(
... (cssSelector, request), interfaces.IRenderer)
>>> renderer.update()
>>> print renderer.render()
label
The renderer for the subscription must correctly hook up the script (handler) as the event listener for the element. So let’s create a subscription:
>>> def handler(event, selector, request): ... return 'alert("Here!");'>>> subscription = jsevent.JSSubscription( ... jsevent.DBLCLICK, selector, handler)
Let’s now register the renderer:
>>> import zope.component
>>> zope.component.provideAdapter(jqueryrenderer.JQuerySubscriptionRenderer)
Now we can render the subscription:
>>> renderer = zope.component.getMultiAdapter(
... (subscription, request), interfaces.IRenderer)
>>> renderer.update()
>>> print renderer.render()
$("#form-id").bind("dblclick", function(event){alert("Here!");});
The subscriptions manager renderer must then be able to combine all subscriptions and make sure that they are loaded once the document is ready for them.
>>> subscriptions = jsevent.JSSubscriptions()
>>> subscriptions.subscribe(jsevent.CLICK, selector, handler)
<JSSubscription event=<JSEvent "click">,
selector=<IdSelector "form-id">,
handler=<function handler at ...>>
>>> subscriptions.subscribe(jsevent.DBLCLICK, selector, handler)
<JSSubscription event=<JSEvent "dblclick">,
selector=<IdSelector "form-id">,
handler=<function handler at ...>>
Let’s now register the renderer:
>>> import zope.component
>>> zope.component.provideAdapter(jqueryrenderer.JQuerySubscriptionsRenderer)
Now we can render the subscriptions:
>>> renderer = zope.component.getMultiAdapter(
... (subscriptions, request), interfaces.IRenderer)
>>> renderer.update()
>>> print renderer.render()
$(document).ready(function(){
$("#form-id").bind("click", function(event){alert("Here!");});
$("#form-id").bind("dblclick", function(event){alert("Here!");});
})
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/@@ajax/validate" +
"?widget-name=zip&form.zip=" + $("#form-zip").val(),
function(msg){applyErrorMessage("form-zip", msg)}
)
This renderer defines how JavaScript switches the widget between display and input mode. This particular implementation actually leaves all the work up to a JavaScript function called switchWidget('widget-id', html) passing in the widget id of the widget to switch and the HTML with which the old content is replaced with.
So let’s create a widget switcher instance:
>>> from zope.site.folder import rootFolder >>> root = rootFolder() >>> form = Form(root, request) >>> form.__name__ = 'form.html'>>> widget = Widget(request) >>> widget.id = 'form-zip' >>> widget.name = 'form.zip' >>> widget.__name__ = 'zip'>>> from z3c.formjs import jsswitch >>> switcher = jsswitch.WidgetSwitcher(form, widget, 'display')
Let’s now register the renderer:
>>> zope.component.provideAdapter(
... jqueryrenderer.JQueryWidgetSwitcherRenderer)
Now we can render the script:
>>> renderer = zope.component.getMultiAdapter(
... (switcher, request), interfaces.IRenderer)
>>> renderer.update()
>>> print renderer.render()
$.get("http://127.0.0.1/form.html/@@ajax/getDisplayWidget?widget-name=zip",
function(html){switchWidget("form-zip", "display", html)}
)
This renderer defines how JavaScript switches the widget to input mode when clicking on the label.
So let’s create a label widget switcher instance:
>>> from z3c.formjs import jsswitch
>>> switcher = jsswitch.LabelWidgetSwitcher(request, 'input')
Let’s now register the renderer:
>>> zope.component.provideAdapter(
... jqueryrenderer.JQueryLabelWidgetSwitcherRenderer)
Now we can render the script:
>>> renderer = zope.component.getMultiAdapter(
... (switcher, request), interfaces.IRenderer)
>>> renderer.update()
>>> print renderer.render()
$.get("http://127.0.0.1/@@ajax/getInputWidget?widget-id=" +
event.target.parentNode.attributes["for"].value,
function(html){switchWidget(event.target.parentNode.attributes["for"].value,
"input", html)}
)
This renderer defines how JavaScript saves the value of a widget. The widget submits the data to the form and waits for the response. The response and the widget id are then forwarded to a JavaScript function saveWidget('widget-id', 'message'). The function must return a boolean stating whether an error occurred. The renderer also decides whether to switch back to display mode.
So let’s create a widget saver instance:
>>> root = rootFolder() >>> form = Form(root, request) >>> form.__name__ = 'form.html'>>> widget = Widget(request) >>> widget.id = 'form-zip' >>> widget.name = 'form.zip' >>> widget.__name__ = 'zip'>>> saver = jsswitch.WidgetSaver(form, widget)
Let’s now register the renderer:
>>> zope.component.provideAdapter(
... jqueryrenderer.JQueryWidgetSaverRenderer)
Now we can render the script:
>>> renderer = zope.component.getMultiAdapter(
... (saver, request), interfaces.IRenderer)
>>> renderer.update()
>>> print renderer.render()
$.get("http://127.0.0.1/form.html/@@ajax/saveWidgetValue?widget-name=zip&form.zip=" + $("#form-zip").val(),
function(msg){error=saveWidget("form-zip", msg);
if (error == false) {$.get("http://127.0.0.1/form.html/@@ajax/getDisplayWidget?widget-name=zip",
function(html){switchWidget("form-zip", "display", html)}
)}}
)