diff --git a/demo/moulinrouge/templates/table.jinja2 b/demo/moulinrouge/templates/table.jinja2
index a9cdf31..1fa361f 100644
--- a/demo/moulinrouge/templates/table.jinja2
+++ b/demo/moulinrouge/templates/table.jinja2
@@ -7,6 +7,9 @@
Total
{{ chart.render_table(total=True) }}
+ Style
+ {{ chart.render_table(total=True, style=True) }}
+
Transposed
{{ chart.render_table(transpose=True) }}
diff --git a/pygal/table.py b/pygal/table.py
index 751ffb4..1b1e238 100644
--- a/pygal/table.py
+++ b/pygal/table.py
@@ -22,7 +22,9 @@ Table maker
"""
from pygal.graph.base import BaseGraph
+from pygal.util import template
from lxml.html import builder, tostring
+import uuid
class HTML(object):
@@ -42,26 +44,30 @@ class Table(BaseGraph):
self.__dict__.update(config.to_dict())
self.config = config
- def render(self, total=False, transpose=False):
+ def render(self, total=False, transpose=False, style=False):
html = HTML()
+ attrs = {}
+
+ if style:
+ attrs['id'] = 'table-%s' % uuid.uuid4()
+
table = []
_ = lambda x: x if x is not None else ''
- table.append([None])
- labels = []
if self.x_labels:
- labels += self.x_labels
- if len(labels) < self._len:
- labels += [None] * (self._len - len(labels))
- if len(labels) > self._len:
- labels = labels[:self._len]
-
- for label in labels:
- table[0].append(label)
+ labels = list(self.x_labels)
+ if len(labels) < self._len:
+ labels += [None] * (self._len - len(labels))
+ if len(labels) > self._len:
+ labels = labels[:self._len]
+ table.append(labels)
if total:
- table[0].append('Total')
+ if len(table):
+ table[0].append('Total')
+ else:
+ table.append([None] * (self._len + 1) + ['Total'])
acc = [0] * (self._len + 1)
for i, serie in enumerate(self.series):
@@ -96,15 +102,63 @@ class Table(BaseGraph):
if not transpose:
table = list(zip(*table))
- table = tostring(
- html.table(
+ thead = []
+ tbody = []
+ tfoot = []
+
+ if not transpose or self.x_labels:
+ # There's always series title but not always x_labels
+ thead = [table[0]]
+ tbody = table[1:]
+ else:
+ tbody = table
+
+ parts = []
+ if thead:
+ parts.append(
+ html.thead(
+ *[html.tr(
+ *[html.th(_(col)) for col in r]
+ ) for r in thead]
+ )
+ )
+ if tbody:
+ parts.append(
html.tbody(
*[html.tr(
*[html.td(_(col)) for col in r]
- ) for r in table]
+ ) for r in tbody]
)
)
+ if tfoot:
+ parts.append(
+ html.tfoot(
+ *[html.tr(
+ *[html.th(_(col)) for col in r]
+ ) for r in tfoot]
+ )
+ )
+
+ table = tostring(
+ html.table(
+ *parts, **attrs
+ )
)
+ if style:
+ if style is True:
+ css = '''
+ #{{ id }}{
+ width: 100%;
+ }
+ #{{ id }} tbody tr:nth-child(odd) td {
+ background-color: #f9f9f9;
+ }
+ '''
+ else:
+ css = style
+ table = tostring(html.style(
+ template(css, **attrs),
+ scoped='scoped')) + table
if self.disable_xml_declaration:
table = table.decode('utf-8')
return table