{% endfor %}
diff --git a/layerindex/widgets.py b/layerindex/widgets.py
new file mode 100644
index 0000000..d0bd6d9
--- /dev/null
+++ b/layerindex/widgets.py
@@ -0,0 +1,69 @@
+# Based on parts of forms/widgets.py from Django
+#
+# Copyright (c) Django Software Foundation and individual contributors.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# 3. Neither the name of Django nor the names of its contributors may be used
+# to endorse or promote products derived from this software without
+# specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+import django.forms
+from django.forms.widgets import CheckboxInput
+from django.utils.encoding import force_unicode
+from django.utils.html import escape, conditional_escape
+from django.utils.safestring import mark_safe
+from itertools import chain
+
+# Reworked CheckboxSelectMultiple
+class TableCheckboxSelectMultiple(django.forms.SelectMultiple):
+ def render(self, name, value, attrs=None, choices=()):
+ if value is None: value = []
+ has_id = attrs and 'id' in attrs
+ final_attrs = self.build_attrs(attrs, name=name)
+ output = [u'
']
+ # Normalize to strings
+ str_values = set([force_unicode(v) for v in value])
+ for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
+ # If an ID attribute was given, add a numeric index as a suffix,
+ # so that the checkboxes don't all have the same ID attribute.
+ if has_id:
+ final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
+ label_for = u' for="%s"' % final_attrs['id']
+ else:
+ label_for = ''
+
+ cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
+ option_value = force_unicode(option_value)
+ rendered_cb = cb.render(name, option_value)
+ option_label = conditional_escape(force_unicode(option_label))
+ output.append(u'