Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from
Apr 30, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 47 additions & 16 deletions substanced/folder/templates/contents.pt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -40,24 +40,56 @@
-- all -- -- all --
</label> </label>


<div id="choices"> <div id="choices" class="row" tal:condition="not batch.multicolumn">


<tal:loop tal:repeat="choice batch.items"> <div class="span3">
<tal:block condition="choice['viewable']"> <tal:loop tal:repeat="choice batch.items">
<label class="checkbox" for="delete-${repeat.choice.index}"> <tal:block condition="choice['viewable']">
<i class="${choice['icon']}"> </i> <label class="checkbox" for="delete-${repeat.choice.index}">
<input tal:attributes="disabled not choice['deletable']" <i class="${choice['icon']}"> </i>
type="checkbox" <input tal:attributes="disabled not choice['deletable']"
name="delete" type="checkbox"
value="${choice['name']}" name="delete"
id="delete-${repeat.choice.index}"/> value="${choice['name']}"
<a href="${choice['url']}">${choice['name']}</a> id="delete-${repeat.choice.index}"/>
</label> <a href="${choice['url']}">${choice['name']}</a>
</tal:block> </label>
</tal:loop> </tal:block>
</tal:loop>
</div>


</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> </div>


<input type="hidden" name="csrf_token" <input type="hidden" name="csrf_token"
Expand Down Expand Up @@ -85,7 +117,6 @@
</ul> </ul>
</div> </div>
</div> </div>

</fieldset> </fieldset>
</form> </form>


Expand Down
56 changes: 55 additions & 1 deletion substanced/util/__init__.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -142,10 +142,31 @@ class Batch(object):
``True`` if either ``next_url`` or ``prev_url`` are ``True`` (meaning ``True`` if either ``next_url`` or ``prev_url`` are ``True`` (meaning
batching is required). 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. 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: if url is None:
url = request.url url = request.url


Expand All @@ -163,6 +184,17 @@ def __init__(self, seq, request, url=None, default_size=15):
if size < 1: if size < 1:
size = default_size 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 start = num * size
end = start + size end = start + size
items = seq[start:end] items = seq[start:end]
Expand All @@ -173,6 +205,7 @@ def __init__(self, seq, request, url=None, default_size=15):
prev_url = None prev_url = None
next_url = None next_url = None
last_url = None last_url = None
toggle_url = None


if num: if num:
first_url = merge_url_qs(url, batch_size=size, batch_num=0) first_url = merge_url_qs(url, batch_size=size, batch_num=0)
Expand All @@ -183,17 +216,38 @@ def __init__(self, seq, request, url=None, default_size=15):
if size and (num < last): if size and (num < last):
last_url = merge_url_qs(url, batch_size=size, batch_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.items = items
self.num = num self.num = num
self.size = size self.size = size
self.length = length self.length = length
self.required = bool(prev_url or next_url) 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.first_url = first_url
self.prev_url = prev_url self.prev_url = prev_url
self.next_url = next_url self.next_url = next_url
self.last_url = last_url self.last_url = last_url
self.last = last 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): def chunks(stream, chunk_size=10000):
""" Return a generator that will iterate over a stream (a filelike """ Return a generator that will iterate over a stream (a filelike
object) ``chunk_size`` bytes at a time.""" object) ``chunk_size`` bytes at a time."""
Expand Down
22 changes: 22 additions & 0 deletions substanced/util/tests.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -183,6 +183,28 @@ def test_it_size_zero(self):
self.assertEqual(inst.items, seq) self.assertEqual(inst.items, seq)
self.assertEqual(inst.size, 15) 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): class Test_merge_url_qs(unittest.TestCase):
def _callFUT(self, url, **kw): def _callFUT(self, url, **kw):
from . import merge_url_qs from . import merge_url_qs
Expand Down