Welcome, guest | Sign In | My Account | Store | Cart

The beginnings of a class for "animating" plain HTML to produce a dynamic HTML output as an alternative to a templating language. It's inspired by Ruby's hquery library, which describes itself as "unobtrusive server scripting".

Python, 75 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from lxml import etree
from pyquery.pyquery import PyQuery

class Animator(PyQuery):
    
    def listfill(self, selector, data):
        """Bind list of items to HTML list. In the event of selector yielding 
        more than prototype item, these are cycled over to be cloned and filled.
        """
        proto = self(selector)
        parent = proto.parent()
        proto.remove()
        N = len(proto)
        for idx, item in enumerate(data):
            parent.append(proto.eq(idx % N).clone().text(item))
        
    def tablefill(self, selector, subselector, data):
        """Bind list of tuples to table. Typically selector='tr' and
        subselector='td'.  In the event of selector yielding more than
        one row, these are cycled over to be cloned and filled."""
        proto = self(selector)
        parent = proto.parent()
        proto.remove()
        N = len(proto)
        for idx, row in enumerate(data):
            parent.append(proto.eq(idx % N).clone().rowfill(subselector, row))
    
    def rowfill(self, selector, values):
        """Bind array to selector's children's text nodes. Length of values
        must be no greater than children available in selector."""
        q = self(selector)
        for idx, value in enumerate(values):
            q.eq(idx).text(value)
        return self
    
    
def test():
    template = '''
    <table id="nametable">
    <tr style="text-color:red"><td>Lorem</td><td>Ipsum</td>
    <tr><td>Lorem</td><td>Ipsum</td>
    </table>
    <p id="error">Error in names</p>
    <p>Your name is <span id="username">Lorem Ipsum</span></p>
    <ul id="namelist">
    <li>Lorem Ipsum</li>
    </ul>
    '''
    data = [('John', 'Smith'), ('Joe', 'Bloggs'), ('Razor', 'Blade')]
    names = ['John Smith', 'Joe Blogs']
    t = Animator(template)
    t('#nametable').tablefill('tr', 'td', data)
    t('#nametable').attr.border = '1'
    t('#namelist').listfill('li', names)
    t('#error').remove()
    t('#username').text('Jimmy Choo')
    print t
    return t

if __name__ == "__main__":
    test()

# Resulting output
"""
<div><table id="nametable" border="1"><tr style="text-color:red"><td>John</td><td>Smith</td>
    </tr><tr><td>Joe</td><td>Bloggs</td>
    </tr><tr style="text-color:red"><td>Razor</td><td>Blade</td>
    </tr></table> 
    <p>Your name is <span id="username">Jimmy Choo</span></p>
    <ul id="namelist"> 
    <li>John Smith</li>
    <li>Joe Blogs</li>
    </ul></div>

"""

HTML template animation enables the designer to work in Dreamweaver or other HTML prototyping tool and the developer to use the bare HTML as a template. Normally the developer would have to convert the HTML to a templating language, which is fine once off but becomes a pain when the designer makes improvements to the original HTML.

The class adds HTML-munging convenience methods for binding data to lists and tables on top of [PyQuery](pypi.python.org/pypi/pyquery), which is a re-implementation of the easy-to-use jQuery API in Python.