Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

first attempt at a single/multi-column toggle for folder contents #5

Merged
merged 4 commits into from

2 participants

@ericrasmussen

I added functionality to substanced.util.Batch to accommodate a toggle link for multi-column and single column views, including test coverage (although it could likely use a couple of additional tests, so let me know what you think and I can add them).

Note: the div id="choices" section of contents.pt appears to have changed dramatically, but the large diff is the result of wrapping it in another div element and indenting each line to accommodate the change. The benefit to wrapping it in the extra div is that you need to click inside that div to check a checkbox, rather than being able to accidentally check boxes by clicking on the other side of the screen.

@mcdonc mcdonc merged commit 8a52c58 into Pylons:master
@mcdonc
Owner

Looks good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 24, 2012
  1. @ericrasmussen
Commits on Apr 26, 2012
  1. @ericrasmussen
Commits on Apr 27, 2012
  1. @ericrasmussen
Commits on Apr 29, 2012
  1. @ericrasmussen
This page is out of date. Refresh to see the latest.
View
63 substanced/folder/templates/contents.pt
@@ -40,24 +40,56 @@
-- all --
</label>
- <div id="choices">
-
- <tal:loop tal:repeat="choice batch.items">
- <tal:block condition="choice['viewable']">
- <label class="checkbox" for="delete-${repeat.choice.index}">
- <i class="${choice['icon']}"> </i>
- <input tal:attributes="disabled not choice['deletable']"
- type="checkbox"
- name="delete"
- value="${choice['name']}"
- id="delete-${repeat.choice.index}"/>
- <a href="${choice['url']}">${choice['name']}</a>
- </label>
- </tal:block>
- </tal:loop>
+ <div id="choices" class="row" tal:condition="not batch.multicolumn">
+
+ <div class="span3">
+ <tal:loop tal:repeat="choice batch.items">
+ <tal:block condition="choice['viewable']">
+ <label class="checkbox" for="delete-${repeat.choice.index}">
+ <i class="${choice['icon']}"> </i>
+ <input tal:attributes="disabled not choice['deletable']"
+ type="checkbox"
+ name="delete"
+ value="${choice['name']}"
+ id="delete-${repeat.choice.index}"/>
+ <a href="${choice['url']}">${choice['name']}</a>
+ </label>
+ </tal:block>
+ </tal:loop>
+ </div>
</div>
+ <div id="choices" tal:condition="batch.multicolumn">
+
+ <div class="row-fluid" tal:define="position 0">
+ <tal:loop tal:repeat="column batch.make_columns()">
+ <div class="span3">
+ <tal:loop tal:repeat="choice column">
+ <tal:block condition="choice['viewable']">
+ <label class="checkbox" for="delete-${position}">
+ <i class="${choice['icon']}"> </i>
+ <input tal:attributes="disabled not choice['deletable']"
+ type="checkbox"
+ name="delete"
+ value="${choice['name']}"
+ id="delete-${position}"/>
+ <a href="${choice['url']}">${choice['name']}</a>
+ </label>
+ </tal:block>
+ <?python position += 1 ?>
+ </tal:loop>
+ </div>
+ </tal:loop>
+ </div>
+ </div>
+
+ </div>
+
+ <div class="row-fluid" tal:condition="batch.required">
+ <div class="span2">
+ <a class="btn" href="${batch.toggle_url}">${batch.toggle_text}</a>
+ </div>
</div>
<input type="hidden" name="csrf_token"
@@ -85,7 +117,6 @@
</ul>
</div>
</div>
-
</fieldset>
</form>
View
56 substanced/util/__init__.py
@@ -142,10 +142,31 @@ class Batch(object):
``True`` if either ``next_url`` or ``prev_url`` are ``True`` (meaning
batching is required).
+ ``multicolumn``
+
+ ``True`` if the current view should be rendered in multiple columns.
+
+ ``toggle_url``
+
+ The URL to be used for the multicolumn/single column toggle button. The
+ ``batch_size``, ``batch_num``, and ``multicolumn`` parameters are
+ converted to their multicolumn or single column equivalents. If a user
+ is viewing items 40-80 in multiple columns, the toggle will switch to
+ items 40-50 in a single column. If a user is viewing items 50-60 in a
+ single column, the toggle will switch to items 40-80 in multiple columns.
+
+ ``toggle_text``
+
+ The text to display on the multi-column/single column toggle.
+
The ``seq`` passed must define ``__len__`` and ``__slice__`` methods.
+
+ ``make_columns``
+
+ A method to split ``items`` into a nested list representing columns.
"""
- def __init__(self, seq, request, url=None, default_size=15):
+ def __init__(self, seq, request, url=None, default_size=10, toggle_size=40):
if url is None:
url = request.url
@@ -163,6 +184,17 @@ def __init__(self, seq, request, url=None, default_size=15):
if size < 1:
size = default_size
+ multicolumn = request.params.get('multicolumn', '') == 'True'
+
+ # create multicolumn/single column toggle attributes
+ if multicolumn:
+ toggle_num = size * num / default_size
+ toggle_size = default_size
+ toggle_text = 'Single column'
+ else:
+ toggle_num = size * num / toggle_size
+ toggle_text = 'Multi-column'
+
start = num * size
end = start + size
items = seq[start:end]
@@ -173,6 +205,7 @@ def __init__(self, seq, request, url=None, default_size=15):
prev_url = None
next_url = None
last_url = None
+ toggle_url = None
if num:
first_url = merge_url_qs(url, batch_size=size, batch_num=0)
@@ -183,17 +216,38 @@ def __init__(self, seq, request, url=None, default_size=15):
if size and (num < last):
last_url = merge_url_qs(url, batch_size=size, batch_num=last)
+ if prev_url or next_url:
+ toggle_url = merge_url_qs(
+ url,
+ batch_size=toggle_size,
+ batch_num=toggle_num,
+ multicolumn=not multicolumn,
+ )
+
self.items = items
self.num = num
self.size = size
self.length = length
self.required = bool(prev_url or next_url)
+ self.multicolumn = multicolumn
+ self.toggle_url = toggle_url
+ self.toggle_text = toggle_text
self.first_url = first_url
self.prev_url = prev_url
self.next_url = next_url
self.last_url = last_url
self.last = last
+ def make_columns(self, column_size=10, num_columns=4):
+ """ Break ``self.items`` into a nested list representing columns."""
+ columns = []
+ for i in range(num_columns):
+ start = i * column_size
+ end = start + column_size
+ part = self.items[start:end]
+ columns.append(part)
+ return columns
+
def chunks(stream, chunk_size=10000):
""" Return a generator that will iterate over a stream (a filelike
object) ``chunk_size`` bytes at a time."""
View
22 substanced/util/tests.py
@@ -183,6 +183,28 @@ def test_it_size_zero(self):
self.assertEqual(inst.items, seq)
self.assertEqual(inst.size, 15)
+ def test_it_multicolumn_toggle_text(self):
+ seq = [1,2,3,4,5,6]
+ request = testing.DummyRequest()
+ request.params['multicolumn'] = 'True'
+ inst = self._makeOne(seq, request)
+ self.assertEqual(inst.toggle_text, 'Single column')
+
+ def test_it_not_multicolumn_toggle_text(self):
+ seq = [1,2,3,4,5,6]
+ request = testing.DummyRequest()
+ request.params['multicolumn'] = 'False'
+ inst = self._makeOne(seq, request)
+ self.assertEqual(inst.toggle_text, 'Multi-column')
+
+ def test_it_make_columns(self):
+ seq = [1,2,3,4,5,6]
+ request = testing.DummyRequest()
+ inst = self._makeOne(seq, request)
+ cols = inst.make_columns(column_size=2, num_columns=3)
+ expected = [ [1,2], [3,4], [5,6] ]
+ self.assertEqual(cols, expected)
+
class Test_merge_url_qs(unittest.TestCase):
def _callFUT(self, url, **kw):
from . import merge_url_qs
Something went wrong with that request. Please try again.