[svn] added `|batch` and `|slice` jinja filters
authorArmin Ronacher <armin.ronacher@active-4.com>
Fri, 13 Apr 2007 20:32:11 +0000 (22:32 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Fri, 13 Apr 2007 20:32:11 +0000 (22:32 +0200)
--HG--
branch : trunk

CHANGES
docs/src/index.txt
jinja/filters.py
tests/runtime/columntest.py [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 18545e5a2e25083ab4e2648239a41ae3cc6b72ed..ed389413bfcd58d330574a8b99850e450b2bc335 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -35,6 +35,10 @@ Version 1.1
 - fixed severe memcaching bug. Formerly it wasn't possible to use memcaching
   without enabling disk cache.
 
+- fixed a bug that allowed users to override the special names `_`, `true` etc.
+
+- added `batch` and `slice` filters
+
 
 Version 1.0
 -----------
index 6253ec8f12f66a6f12a5cfc2e510572220d313e7..9e9ad4c5d49877a385305ce8bb958fbf0ddddf10 100644 (file)
@@ -30,7 +30,7 @@ Welcome in the Jinja documentation.
 
   - `Internationalization <i18n.txt>`_
 
-  - `Recipies <devrecipies.txt>`_
+  - `Developer Recipies <devrecipies.txt>`_
 
 - Template Designer Documentation:
 
@@ -38,6 +38,6 @@ Welcome in the Jinja documentation.
 
   - `Differences To Django <fromdjango.txt>`_
 
-  - `Recipies <recipies.txt>`_
+  - `Designer Recipies <recipies.txt>`_
 
 There is also support via IRC on the ``#pocoo`` channel on `irc.freenode.net`.
index f54aaa1930397b5a560aa8560e4ef7cff82ec853..e77b8912aa8b55a0ac7676590011554445bef8f3 100644 (file)
@@ -618,6 +618,83 @@ def do_capture(name='captured', clean=False):
     return wrapped
 
 
+def do_slice(slices, fill_with=None):
+    """
+    Slice an iterator and return a list of lists containing
+    those items. Useful if you want to create a div containing
+    three div tags that represent columns:
+
+    .. sourcecode:: jinja
+
+        <div class="columwrapper">
+          {%- for column in items|slice(3) %}
+            <ul class="column-{{ loop.index }}">
+            {%- for item in column %}
+              <li>{{ item }}</li>
+            {%- endfor %}
+            </ul>
+          {%- endfor %}
+        </div>
+
+    *New in Jinja 1.1*
+    """
+    def wrapped(env, context, value):
+        result = []
+        seq = list(value)
+        length = len(seq)
+        items_per_slice = length // slices
+        slices_with_extra = length % slices
+        offset = 0
+        for slice_number in xrange(slices):
+            start = offset + slice_number * items_per_slice
+            if slice_number < slices_with_extra:
+                offset += 1
+            end = offset + (slice_number + 1) * items_per_slice
+            tmp = seq[start:end]
+            if fill_with is not None and slice_number >= slices_with_extra:
+                tmp.append(fill_with)
+            result.append(tmp)
+        return result
+    return wrapped
+
+
+def do_batch(linecount, fill_with=None):
+    """
+    A filter that batches items. It works pretty much like `slice`
+    just the other way round. It returns a list of lists with the
+    given number of items. If you provide a second parameter this
+    is used to fill missing items. See this example:
+
+    .. sourcecode:: jinja
+
+        <table>
+        {%- for row in items|batch(3, '&nbsp;') %}
+          <tr>
+          {%- for column in row %}
+            <tr>{{ column }}</td>
+          {%- endfor %}
+          </tr>
+        {%- endfor %}
+        </table>
+
+    *New in Jinja 1.1*
+    """
+    def wrapped(env, context, value):
+        result = []
+        tmp = []
+        for item in value:
+            if len(tmp) == linecount:
+                result.append(tmp)
+                tmp = []
+            tmp.append(item)
+        if tmp:
+            if fill_with is not None and len(tmp) < linecount:
+                tmp += [fill_with] * (linecount - len(tmp))
+            result.append(tmp)
+        return result
+    return wrapped
+
+
 FILTERS = {
     'replace':              do_replace,
     'upper':                do_upper,
@@ -655,5 +732,7 @@ FILTERS = {
     'urlize':               do_urlize,
     'format':               do_format,
     'capture':              do_capture,
-    'trim':                 do_trim
+    'trim':                 do_trim,
+    'slice':                do_slice,
+    'batch':                do_batch
 }
diff --git a/tests/runtime/columntest.py b/tests/runtime/columntest.py
new file mode 100644 (file)
index 0000000..ebb00fc
--- /dev/null
@@ -0,0 +1,57 @@
+import jdebug
+from jinja import from_string
+
+
+template = from_string(u'''\
+<h1>Unfilled</h1>
+<div class="index">
+  {%- for column in items|slice(3) %}
+  <div class="col-{{ loop.index }}">
+    <ul>
+    {%- for item in column %}
+      <li>{{ item }}</li>
+    {%- endfor %}
+    </ul>
+  </div>
+  {%- endfor %}
+</div>
+
+<h1>Filled</h1>
+<div class="index">
+  {%- for column in items|slice(3, 'missing') %}
+  <div class="col-{{ loop.index }}">
+    <ul>
+    {%- for item in column %}
+      <li>{{ item }}</li>
+    {%- endfor %}
+    </ul>
+  </div>
+  {%- endfor %}
+</div>
+
+<h1>Filled Table</h1>
+<table>
+  {%- for row in items|batch(3, '&nbsp;') %}
+  <tr>
+    {%- for column in row %}
+    <td>{{ column }}</td>
+    {%- endfor %}
+  </tr>
+  {%- endfor %}
+</table>
+
+<h1>Unfilled Table</h1>
+<table>
+  {%- for row in items|batch(3) %}
+  <tr>
+    {%- for column in row %}
+    <td>{{ column }}</td>
+    {%- endfor %}
+    {%- if row|length < 3 %}
+    <td colspan="{{ 3 - (row|length) }}">&nbsp;</td>
+    {%- endif %}
+  </tr>
+  {%- endfor %}
+</table>''')
+
+print template.render(items=range(16))