====================
Renderers for JQuery
====================

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


``IdSelector`` Renderer
-----------------------

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


``JSSubscription`` Renderer
---------------------------

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!");});


``JSSubscriptions`` Renderer
----------------------------

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!");});
  })

``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/@@ajax/validate" +
            "?widget-name=zip&form.zip=" + $("#form-zip").val(),
        function(msg){applyErrorMessage("form-zip", msg)}
  )
