Add my frozen perl talk
[gitmo/moose-htdocs.git] / template_test.html
1 <html>
2 <head>
3 <script language="javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.2.6.js"></script>
4 <script language="javascript">
5
6 /*
7
8 COPYRIGHT AND LICENCE
9
10 Copyright (C) 2006-2008 Infinity Interactive, Inc.
11
12 http://www.iinteractive.com
13
14 This library is free software; you can redistribute it 
15 and/or modify it under the same terms as Perl itself. 
16
17 */
18
19 /**************** Templating Objects ****************/
20
21 function Param (value) { this.value = value }
22 Param.prototype.find_and_replace = function (template, selector, value) {
23     template.find(selector)
24             .each(function () { jQuery(this).html(value) })
25 }
26 Param.prototype.render = function (template, selector) {
27     this.find_and_replace(template, selector, this.value);    
28 }
29
30 function Thunk (func) {
31     this.func = func;
32 }
33 Thunk.prototype        = new Param ();
34 Thunk.prototype.render = function (template, selector) {
35     this.find_and_replace(
36         template, 
37         selector, 
38         this.func(template, selector)
39     );    
40 }
41
42 function MethodThunk (invocant, method_name) {
43     this.func = function () { return invocant[method_name]() }
44 }
45 MethodThunk.prototype = new Thunk ();
46
47 function PropertyThunk (invocant, property_name) {
48     this.func = function () { return invocant[property_name] }
49 }
50 PropertyThunk.prototype = new Thunk ();
51
52 function Collection (params) {
53     this.css_selector = params['css_selector'];
54     this.values       = params['values'];
55     this.transformer  = params['transformer'];
56 }
57 Collection.prototype            = new Param ();
58 Collection.prototype.get_values = function () {
59     return (this.transformer == undefined)
60         ? this.values
61         : jQuery.map(this.values, this.transformer)
62 }
63 Collection.prototype.render     = function (template, selector) {
64     var selection = template.find(selector).find(this.css_selector);
65     var target    = selection.parent();
66     target.empty();
67     jQuery.each(
68         this.get_values(),
69         function () { 
70             target.append(
71                 selection.clone(true).process_template(this)
72             ) 
73         }
74     );    
75 }
76
77 function Hierarchy (params) {
78     this.list_selector = params['list_selector'];
79     this.item_selector = params['item_selector'];
80     this.values        = params['values'];
81 }
82 Hierarchy.prototype            = new Param ();
83 Hierarchy.prototype.get_values = function () { return this.values }
84 Hierarchy.prototype.render     = function (template, selector) {
85     var selection      = template.find(selector);
86     var list_selection = selection.find(this.list_selector);
87     var item_selection = selection.find(this.item_selector);
88
89     selection.empty();
90     list_selection.empty();
91
92     var traverse = function (element, tree) {
93         // build a node ...
94         var node_element = item_selection.clone(true).process_template(
95             tree['node']
96         );
97         element.append(node_element);
98         // if the node has children then ...
99         if (tree['children'] != undefined) {
100             var new_element = list_selection.clone(true);
101             jQuery.each(
102                 tree['children'],
103                 function () {
104                     traverse(new_element, this);
105                     node_element.append(new_element);
106                 }
107             );
108         }
109     };
110     
111     // create the root ...
112     var root_node = list_selection.clone(true);
113     traverse(root_node, this.get_values());
114     selection.append(root_node);    
115 }
116
117 /************* JQuery Plugin *******************/
118
119 jQuery.fn.extend({
120     process_template : function (params) {
121         var template = this;
122         jQuery.each(
123             params,
124             function (selector, param) {                    
125                 ((typeof param == 'object')
126                     ? param
127                     : new Param (param)).render(template, selector)
128             }
129         );
130         return template;
131     }
132 });
133
134 /********************** Paramters ***************************/
135
136 function User (name) {
137     this._name = name;
138 }
139 User.prototype.name = function () { return this._name }
140
141 function Product (id, name) {
142     this._id = id;
143     this.name = name;
144 }
145 Product.prototype.get_id = function () { return this._id }
146
147 var params = {
148     '#logo'           : new Thunk (function (t, selector) {
149         t.find(selector).attr({
150             'src'   : 'http://iinteractive.com/images/logo.gif',
151             'style' : 'padding: 10px;',
152         });
153     }),
154     '.username'       : new MethodThunk (new User ('Stevan'), "name"),
155     '#user_quotation' : 'JQuery Rocks',
156     '.copyright'      : new Thunk (function () { return "Copyright (c) " + (new Date ()).getFullYear() }),
157     '#products'       : new Collection ({
158         css_selector  : '.row',
159         values        : [
160             new Product (10, 'Foo'),
161             new Product (11, 'Bar'),
162             new Product (12, 'Baz'),
163         ],
164         transformer   : function (val) {
165             return {
166                 '.id'   : val.get_id(),
167                 '.name' : new PropertyThunk (val, 'name'),
168             }
169         }
170     }),
171     '#dogs'          : new Collection ({
172         css_selector : '.table_row',
173         values       : [
174             { '.sound' : "Bark" },
175             { '.sound' : "Woof" },
176         ]
177     }),
178     '#cats'          : new Hierarchy ({
179         list_selector : '.list',
180         item_selector : '.item',
181         values       : {
182             node     : { '.name' : "Twinkles"  },
183             children : [
184                 { node : { '.name' : "Shnuckums" } },
185                 { 
186                     node     : { '.name' : "Bilbo" },
187                     children : [
188                         { 
189                             node     : { '.name' : "Dweezil" },
190                             children : [
191                                 { node : { '.name' : "Tabby" } },                      
192                             ]
193                         },
194                         { node : { '.name' : "Abraxas"    } },                                                
195                     ]
196                 },
197             ]
198         }
199     }),
200     '#rooms'          : new Hierarchy ({
201         list_selector : '.list',
202         item_selector : '.item',
203         values       : {
204             node     : { '.name' : "Ceiling"  },
205             children : [
206                 { node : { '.name' : "Basement" } },
207                 { 
208                     node     : { '.name' : "Garage" },
209                     children : [
210                         { node : { '.name' : "Root Cellar" } },
211                         { 
212                             node     : { '.name' : "Kitchen" },
213                             children : [
214                                 { node : { '.name' : "Under The Stairs" } },                      
215                             ]
216                         },
217                         { node : { '.name' : "Bathroom"    } },                                                
218                     ]
219                 },
220             ]
221         }
222     }),    
223 };
224
225 $(document).ready(function () {
226     $('body').process_template(params);
227 });
228
229 </script>
230 </head>
231 <body>
232 <img id="logo" src="http://l.yimg.com/a/i/ww/beta/y3.gif" border="1" />
233 <hr/>
234 <div class="username">Foo</div>
235 <hr/>
236 <p id="user_quotation">Text goes here</p>
237 <div id="products" style="border: 1px solid grey; width: 250px">
238     <div class="row" style="border: 1px solid red; padding: 2px; margin: 2px;">
239         <span class="id">ID</span>
240         <span class="name">NAME</span>
241     </div>
242 </div>
243 <br/>
244 <table id="dogs" border="1">
245     <thead>
246         <th>Hello</th>
247     </thead>
248     <tbody>
249         <tr class="table_row">
250             <td>My dog says <span class="sound">NAME</span></td>
251         </tr>
252     </tbody>
253 </table>
254 <hr/>
255 <div id="cats">
256     <ul class="list">
257         <li class="item">My cat is named <span class="name">NAME</span></li>
258     </ul>
259 </div>
260 <hr/>
261 <div id="rooms">
262     <div class="list" style="padding-left: 10px">
263         <div class="item" style="padding-left: 10px">My room is <span class="name">NAME</span></div>
264     </div>
265 </div>
266 <hr/>
267 <div class="username">Foo</div>
268 <hr/>
269 <div class="copyright">Copyleft</div>
270 </body>
271 </html>