Batch navigation
----------------

  >>> from grokcore.component import testing
  >>> testing.grok("zeam.utils.batch")

First we need a content to apply the batch on::

  >>> from zope.interface import implements
  >>> from persistent import Persistent

  >>> class Content(Persistent):
  ...    pass

  >>> app = getRootFolder()
  >>> app['content'] = Content()
  >>> content = app['content']

After we need a batch::

  >>> from zeam.utils.batch import batch
  >>> list_long = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
  >>> b = batch(list_long, count=4)

And a request::

  >>> from zope.publisher.browser import TestRequest
  >>> request = TestRequest()

So we can get the view::

  >>> from zope.component import queryMultiAdapter
  >>> from zeam.utils.batch.interfaces import IBatching
  >>> view = queryMultiAdapter((content, b, request), IBatching)
  >>> print view
  <zeam.utils.batch.views.Batching object at ...>

  >>> from zope.interface.verify import verifyObject
  >>> verifyObject(IBatching, view)
  True

We are on the first page, start is 0::

  >>> view.previous
  >>> view.next
  'http://127.0.0.1/content/++batch++4'
  >>> for b in view.batch:
  ...    print b
  {'url': 'http://127.0.0.1/content', 'style': 'current', 'name': 1}
  {'url': 'http://127.0.0.1/content/++batch++4', 'style': None, 'name': 2}
  {'url': 'http://127.0.0.1/content/++batch++8', 'style': None, 'name': 3}

We can links to first set of elements and the last:

  >>> view.first
  'http://127.0.0.1/content'
  >>> view.last
  'http://127.0.0.1/content/++batch++8'

We set start to 4::

  >>> b = batch(list_long, start=4, count=4)
  >>> view = queryMultiAdapter((content, b, request), IBatching)
  >>> view.previous
  'http://127.0.0.1/content'
  >>> view.next
  'http://127.0.0.1/content/++batch++8'
  >>> for b in view.batch:
  ...    print b
  {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1}
  {'url': 'http://127.0.0.1/content/++batch++4', 'style': 'current', 'name': 2}
  {'url': 'http://127.0.0.1/content/++batch++8', 'style': None, 'name': 3}

  >>> view.first
  'http://127.0.0.1/content'
  >>> view.last
  'http://127.0.0.1/content/++batch++8'

We set start to 8, last page::

  >>> b = batch(list_long, start=8, count=4)
  >>> view = queryMultiAdapter((content, b, request), IBatching)
  >>> view.previous
  'http://127.0.0.1/content/++batch++4'
  >>> view.next
  >>> for b in view.batch:
  ...    print b
  {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1}
  {'url': 'http://127.0.0.1/content/++batch++4', 'style': None, 'name': 2}
  {'url': 'http://127.0.0.1/content/++batch++8', 'style': 'current', 'name': 3}

Now we have less than one page::

  >>> b = batch(['a', 'b',], count=4)
  >>> view = queryMultiAdapter((content, b, request), IBatching)
  >>> view.previous
  >>> view.next
  >>> for b in view.batch:
  ...    print b

  >>> view.first
  'http://127.0.0.1/content'
  >>> view.last
  'http://127.0.0.1/content'

The number of item is modulo to the size of the batch::

  >>> list_short = [1, 2, 3, 4, 5, 6, 7, 8]
  >>> b = batch(list_short, start=4, count=4)
  >>> view = queryMultiAdapter((content, b, request), IBatching)
  >>> view.previous
  'http://127.0.0.1/content'
  >>> view.next
  >>> for b in view.batch:
  ...    print b
  {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1}
  {'url': 'http://127.0.0.1/content/++batch++4', 'style': 'current', 'name': 2}

  >>> view.first
  'http://127.0.0.1/content'
  >>> view.last
  'http://127.0.0.1/content/++batch++4'

If you put a name, it's inserted in the link::

  >>> b = batch(list_long, start=4, count=4, name='video')
  >>> view = queryMultiAdapter((content, b, request), IBatching)
  >>> view.previous
  'http://127.0.0.1/content'
  >>> view.next
  'http://127.0.0.1/content/++batch++video+8'
  >>> for b in view.batch:
  ...    print b
  {'url': 'http://127.0.0.1/content', 'style': None, 'name': 1}
  {'url': 'http://127.0.0.1/content/++batch++video+4', 'style': 'current', 'name': 2}
  {'url': 'http://127.0.0.1/content/++batch++video+8', 'style': None, 'name': 3}


The request form parameters are added to the base url of the batch pages.

  >>> r = TestRequest()
  >>> b = batch(list_long, start=4, count=4, name='video')
  >>> r.form['extraparam'] = 1
  >>> r.form['otherone'] = 'form<>data'
  >>> view_with_params = queryMultiAdapter((content, b, r,), IBatching)

Every parameter in request.form is url encoded and added to the batch URLs.

  >>> view_with_params.first
  'http://127.0.0.1/content?otherone=form%3C%3Edata&extraparam=1'
  >>> view_with_params.last
  'http://127.0.0.1/content/++batch++video+8?otherone=form%3C%3Edata&extraparam=1'


However there is an option not to do this:

  >>> view_with_params.keep_form_data
  True
  >>> view_with_params.keep_form_data = False
  >>> view_with_params.first
  'http://127.0.0.1/content'
  >>> view_with_params.last
  'http://127.0.0.1/content/++batch++video+8'


Rendering
----------

  >>> print view()
  <div class="batchNav">
    <a href="http://127.0.0.1/content" class="previous">
      &lt; Previous</a>
    <a href="http://127.0.0.1/content">1</a>
    <a href="http://127.0.0.1/content/++batch++video+4"
       class="current">2</a>
    <a href="http://127.0.0.1/content/++batch++video+8">3</a>
    <a href="http://127.0.0.1/content/++batch++video+8"
       class="next">
      Next &gt;
    </a>
  </div>


Traversing
----------

  >>> from zope.component import getMultiAdapter
  >>> from zope.traversing.interfaces import ITraversable
  >>> traverser = getMultiAdapter(
  ...                 (content, request), ITraversable, name="batch")

  >>> result = traverser.traverse('4', [])
  >>> assert result is content
  >>> request.form.get('bstart')
  '4'

  >>> result = traverser.traverse('toto+6', [])
  >>> assert result is content
  >>> request.form.get('bstart_toto')
  '6'


Tear down:

  >>> sync()
