We have an informal in-house style that says alternating rows of table data should have different background colors, so that it is easy to keep track of which row is which. This is done by alternating the "class" attribute of each "<tr>" tag. In trying to use Albatross, I wound up doing lots of code like
<al-if expr="i.index() % 2"> <tr> <al-else> <tr class="alt"> </al-if>
Not only is this ugly to look at and a lot to type, it really messes with the head of the HTML editor (I use xemacs) and breaks the indentation.
So we wrote an extension tag <alx-tr> to hide all this nastyness. I include it here in case anyone else finds it interesting.
1 '''
2 A collection of useful custom tag classes for use with the albatross library.
3
4 To make these available, simply pass the class object to the
5 register_tagclasses() member of the application object.
6
7 E.g.:
8
9 import itgatags
10
11 ....
12 class MyApp(SimpleApp):
13 def __init__(self):
14 SimpleApp.__init__(self,......)
15 for page_class in (.......):
16 self .register_page(page_class.name, page_class())
17 for tag_class in (itgatags.TR,):
18 self .register_tagclasses(tag_class)
19
20
21
22 '''
23
24 from albatross.tags import ExprAttrMixin
25 from albatross import EnclosingTag
26
27 class TR(EnclosingTag, ExprAttrMixin):
28 '''
29 <alx-tr expr="..." classes="alt1,alt2,alt3"> ... </alx-tr>
30
31 Similar to <tr>, except that it evaluates expr (which must be an
32 integer) and then chooses a "class=" attribute for the <tr> tag
33 from those listed in the "classes" arg by taking "<expr> % <# of
34 classes>". <expr> is often "i.index()" where i is an iterator
35 created by <al-for>.
36
37 This is useful for having rows of the table with alternating or
38 successive styles. Elements of the "classes" list may be empty
39 (i.e. "alt1,") or the empty string ("alt1,'',alt2") which will
40 produce a <tr> without a "class=" attribute.
41
42 "classes" may be omitted and defaults to ",alt" (i.e. alternating
43 normal and "class=alt" styles. Naturally, you will need some sort
44 of stylesheet definitions for these classes.
45
46 Example:
47 <table>
48 <al-for iter="i" expr="...">
49 <alx-tr expr="i.index()" classes=",alt1,,alt2">
50 <td><al-value expr="i.value().name">.......</td>
51 </alx-tr>
52 </al-for>
53 </table>
54 This will produce a table where the odd rows are normal, but the
55 2nd and 4th rows have special class (and hence presumably special
56 formatting).
57
58 <alx-tr counter="name" classes="'',alt1,alt2"> ... </alx-tr>
59
60 Similar to the above, but instead of evaluating an expression,
61 this uses a counter with the given name in the ctx.locals space
62 (creating it with the value 0 if necessary). The counter will be
63 incremented after it is used. This is useful if a single table
64 contains rows from multiple <al-for> tags, or summary lines at the
65 bottom, or similar. It can also count the number of rows for you!
66
67 Example:
68 <table>
69 <al-for iter="i" expr="...">
70 <alx-tr counter="row">
71 <td><al-value expr="i.value().name">.......</td>
72 </alx-tr>
73 </al-for>
74 <alx-tr counter="row">
75 <td>TOTAL:........</dt>
76 <alx-tr>
77 </table>
78 <al-value expr="row"> Rows Added.
79
80 Using a counter rather than the iterator.index() method ensures
81 that the TOTAL row has the appropriate and consistant class
82 attribute.
83
84 '''
85 name = 'alx-tr'
86
87 def __init__(self, ctx, filename, line_num, attribs):
88 EnclosingTag.__init__(self, ctx, filename, line_num, attribs)
89 if self.has_attrib('expr'):
90 self.compile_expr()
91 self.counter = ''
92 elif self.has_attrib('counter'):
93 self.counter = self.get_attrib('counter')
94 else:
95 self.raise_error('missing "counter" or "expr" attribute')
96 if self.has_attrib('classes'):
97 cs = self.get_attrib('classes')
98 self.classes = []
99 for c in cs.split(','):
100 if c == "''" or c == '""':
101 c = ''
102 self.classes.append(c)
103 else:
104 self.classes = ['', 'alt']
105
106 def to_html(self, ctx):
107 if self.counter:
108 if ctx.has_value(self.counter):
109 val = ctx.get_value(self.counter)
110 else:
111 val = 0
112 else: # expr
113 val = int(ctx.eval_expr(self.expr))
114
115 cls = self.classes[val % len(self.classes)]
116 if cls:
117 ctx.write_content('<tr class="%s">' % cls)
118 else:
119 ctx.write_content('<tr>')
120
121 self.content.to_html(ctx)
122 ctx.write_content('</tr>\n')
123
124 if self.counter:
125 ctx.set_value(self.counter, val + 1)