flexlayout-rails 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,615 @@
1
+ /*!
2
+ * HTML code generator module
3
+ * Copyright (c) 2011-2012 Pablo Escalada
4
+ *
5
+ * Contributor(s):
6
+ * César Acebal
7
+ *
8
+ * MIT Licensed
9
+ */
10
+ (function (templateLayout) {
11
+
12
+ var generator, log;
13
+ log = wef.logger("templateLayout.generator");
14
+
15
+ log.info("load generator module...");
16
+
17
+ function generateRootTemplate(template) {
18
+ var rootElement;
19
+
20
+ function appendFreeNodes(currentNode, defaultNode) {
21
+ var i, className, candidates = [];
22
+ for (i = 0; i < currentNode.childNodes.length; i++) {
23
+ className = currentNode.childNodes[i].className;
24
+ if (className || className === "") {
25
+ //HTMLElementNodes
26
+ if (!/templateLayout/.test(className)) {
27
+ log.log(className, currentNode.childNodes[i].tagName);
28
+ candidates.push(currentNode.childNodes[i]);
29
+ }
30
+ } else {
31
+ //TextNodes
32
+ log.log("text", currentNode.childNodes[i].textContent);
33
+ //insert in template.grid.getDefaultNode()
34
+ candidates.push(currentNode.childNodes[i]);
35
+ }
36
+ }
37
+ while (candidates.length > 0) {
38
+ defaultNode.appendChild(candidates.shift());
39
+ }
40
+ }
41
+
42
+ function generateTemplate(template, parentHtmlNode) {
43
+ var templateNode, gridNode, rowNode, slotNode, defaultSlot, defaultNode;
44
+ log.info("template:", template.selectorText, "(parent:", parentHtmlNode.localName, ")");
45
+ templateNode = generator.fn.appendTemplate(template, parentHtmlNode);
46
+ if (!template.isLeaf()) {
47
+ defaultSlot = template.grid.getDefaultSlot();
48
+ gridNode = generator.fn.appendGrid(template.grid, templateNode);
49
+ template.grid.rows.forEach(function (row) {
50
+ log.info("row:", row.rowText);
51
+ rowNode = generator.fn.appendRow(row, gridNode);
52
+ row.slots.forEach(function (slot) {
53
+ log.info("slot:", slot.slotText);
54
+ slotNode = generator.fn.appendSlot(slot, rowNode);
55
+ if (defaultSlot.slotText === slot.slotText) {
56
+ //mark currentNode as default
57
+ defaultNode = slotNode;
58
+ }
59
+ //each slot can have multiple elements or none
60
+ if (template.grid.filledSlots[slot.slotText]) {
61
+ template.grid.filledSlots[slot.slotText].forEach(function (childTemplate) {
62
+ log.info("slot contains:", childTemplate.selectorText);
63
+ generateTemplate(childTemplate, slotNode);
64
+ });
65
+ }
66
+ });
67
+ });
68
+ appendFreeNodes(templateNode, defaultNode);
69
+ }
70
+ log.debug("template generated: ", template);
71
+ }
72
+
73
+ function resizeTemplateWidth(template, parentHtmlNode) {
74
+ var templateNode, gridNode, columnNode, rowNode, slotNode, availableWidth, computedWidths, availableHeight, computedHeights;
75
+ log.info("resize template - parentWidth:", parentHtmlNode.clientWidth);
76
+ templateNode = template.htmlNode;
77
+ availableWidth = templateNode.clientWidth;
78
+
79
+ if (!template.isLeaf()) {
80
+ computedWidths = generator.fn.computeColWidths(availableWidth, template);
81
+
82
+ gridNode = generator.fn.getGridNode(templateNode);
83
+ generator.fn.setGridNodeWidth(gridNode, computedWidths);
84
+
85
+ columnNode = generator.fn.getColumnNodes(gridNode, template.grid.colNumber);
86
+ generator.fn.setColNodeWidth(columnNode, computedWidths);
87
+
88
+ template.grid.rows.forEach(function (row, rowIndex) {
89
+ log.info("resize row:", row.rowText);
90
+ rowNode = generator.fn.getRowNode(gridNode, rowIndex, columnNode.length);
91
+ row.slots.forEach(function (slot, colIndex) {
92
+ log.info("resize slot:", slot.slotText);
93
+ if (template.grid.filledSlots[slot.slotText]) {
94
+ slotNode = slot.htmlNode;
95
+ generator.fn.setSlotNodeWidth(slotNode, computedWidths, colIndex);
96
+ template.grid.filledSlots[slot.slotText].forEach(function (childTemplate) {
97
+ resizeTemplateWidth(childTemplate, slotNode);
98
+ });
99
+ }
100
+ });
101
+ });
102
+ } else {
103
+ log.log("leaf - no grid");
104
+ }
105
+ log.debug("template resize... [OK]");
106
+ }
107
+
108
+ function resizeTemplateHeight(template, parentHtmlNode) {
109
+ var templateNode, gridNode, columnNode, rowNode, slotNode, computedHeights;
110
+ log.info("resize template - parentHeight:", parentHtmlNode.clientHeight);
111
+ templateNode = template.htmlNode;
112
+
113
+ if (!template.isLeaf()) {
114
+ gridNode = generator.fn.getGridNode(templateNode);
115
+
116
+ columnNode = generator.fn.getColumnNodes(gridNode, template.grid.colNumber);
117
+ template.grid.rows.forEach(function (row, rowIndex) {
118
+ log.info("resize row:", row.rowText);
119
+ rowNode = generator.fn.getRowNode(gridNode, rowIndex, columnNode.length);
120
+
121
+ row.slots.forEach(function (slot, colIndex) {
122
+ log.info("resize slot:", slot.slotText);
123
+ if (template.grid.filledSlots[slot.slotText]) {
124
+ slotNode = slot.htmlNode;
125
+
126
+ template.grid.filledSlots[slot.slotText].forEach(function (childTemplate) {
127
+ resizeTemplateHeight(childTemplate, slotNode);
128
+
129
+ });
130
+ }
131
+ computedHeights = generator.fn.computeRowHeights(template);
132
+ generator.fn.setSlotNodeHeight(slotNode, computedHeights, rowIndex);
133
+ });
134
+ computedHeights = generator.fn.computeRowHeights(template);
135
+ generator.fn.setRowNodeHeight(rowNode, computedHeights, rowIndex);
136
+ });
137
+ computedHeights = generator.fn.computeRowHeights(template);
138
+ generator.fn.setGridNodeHeight(gridNode, computedHeights);
139
+ } else {
140
+ log.log("leaf - no grid");
141
+ }
142
+ log.debug("template resize... [OK]");
143
+ }
144
+
145
+ rootElement = document.querySelector(template.selectorText);
146
+ generateTemplate(template, rootElement.parentNode);
147
+ resizeTemplateWidth(template, rootElement.parentNode);
148
+ resizeTemplateHeight(template, rootElement.parentNode);
149
+ }
150
+
151
+ /**
152
+ * Creates a template compiler
153
+ *
154
+ * @param {r}tom Template Object Model
155
+ *
156
+ * @class Generates HTML code that maps generated TOM to tables, then injects
157
+ * this code into the page DOM.
158
+ * This version uses the old "table layout" method.
159
+ */
160
+ generator = function (tom) {
161
+ return new generator.prototype.init(tom);
162
+ };
163
+
164
+ generator.prototype = {
165
+ /**
166
+ * Local copy of given TOM
167
+ * @type rootTemplate
168
+ */
169
+ tom:undefined,
170
+
171
+ /**
172
+ * @ignore
173
+ * see constructor
174
+ */
175
+ init:function (tom) {
176
+ this.tom = tom;
177
+ return this;
178
+ },
179
+ /**
180
+ * Generates the HTML code and injects it into the page DOM.
181
+ * </p>
182
+ * Code generation is done in three steps:
183
+ * <ul>
184
+ * <li>Step 1: Plain object generation</li>
185
+ * <li>Step 2: Column width resize</li>
186
+ * <li>Step 3: Ror height resize</li>
187
+ * </ul>
188
+ */
189
+ patchDOM:function () {
190
+ log.info("patch DOM...");
191
+ log.debug("TOM: ", this.tom);
192
+ generator.fn.resetCSS();
193
+ this.tom.rows.forEach(generateRootTemplate);
194
+ },
195
+ /**
196
+ * Resets browser default CSS styles.
197
+ */
198
+ resetCSS:function () {
199
+ var head = document.getElementsByTagName('head')[0],
200
+ cssString = [
201
+ ".templateLayout {" +
202
+ "margin: 0;" +
203
+ "padding: 0;" +
204
+ "border: 0;" +
205
+ "font-size: 100%;" +
206
+ "font: inherit;" +
207
+ "vertical-align: baseline;" +
208
+ "line-height: 1;" +
209
+ "border-collapse: collapse;" +
210
+ "border-spacing: 0;" +
211
+ "}"
212
+ ],
213
+ styleTag = document.createElement('style');
214
+ styleTag.setAttribute('type', 'text/css');
215
+ head.appendChild(styleTag);
216
+ styleTag.innerHTML = cssString;
217
+ },
218
+ /**
219
+ * Set grid width (the TABLE node)
220
+ *
221
+ * @param {HTMLElement}gridNode DOM node that maps grid element
222
+ * @param {Object}computedWidths column widths given by calculateColWidths()
223
+ * @param {integer}computedWidths.totalWidth table width
224
+ */
225
+ setGridNodeWidth:function (gridNode, computedWidths) {
226
+ gridNode.style.tableLayout = "fixed";
227
+ gridNode.width = computedWidths.totalWidth;
228
+ },
229
+ /**
230
+ * Set grid height (the TABLE node)
231
+ *
232
+ * @param {HTMLElement}gridNode DOM node that maps grid element
233
+ * @param {Object}computedHeights column widths given by calculateRowHeights()
234
+ * @param {integer}computedHeights.maxHeight table height
235
+ */
236
+ setGridNodeHeight:function (gridNode, computedHeights) {
237
+ gridNode.style.height = computedHeights.totalHeight + "px";
238
+ gridNode.style.maxHeight = computedHeights.totalHeight + "px";
239
+ },
240
+ /**
241
+ * Set columns width (the COL nodes)
242
+ *
243
+ * @param {HTMLElement[]}colNodes array of DOM nodes that maps column nodes
244
+ * @param {Object}computedWidths column widths given by calculateColWidths()
245
+ * @param {integer[]}computedWidths.colWidth array of column widths
246
+ */
247
+ setColNodeWidth:function (colNodes, computedWidths) {
248
+ colNodes.forEach(function (node, index) {
249
+ node.width = computedWidths.colWidth[index];
250
+ node.style.maxWidth = computedWidths.colWidth[index] + "px";
251
+ });
252
+ },
253
+ /**
254
+ * Set row height (the TR nodes)
255
+ *
256
+ * @param {HTMLElement}rowNode DOM node that maps row element
257
+ * @param {Object}computedHeights column widths given by calculateRowHeights()
258
+ * @param {integer[]}computedHeights.rowHeight array of row heights
259
+ * @param {integer}rowIndex row index
260
+ */
261
+ setRowNodeHeight:function (rowNode, computedHeights, rowIndex) {
262
+ rowNode.style.height = computedHeights.rowHeight[rowIndex] + "px";
263
+ rowNode.style.maxHeight = computedHeights.rowHeight[rowIndex] + "px";
264
+ },
265
+ /**
266
+ * Set slot width (the TD nodes)
267
+ *
268
+ * @param {HTMLElement}slotNode DOM node that maps slot element
269
+ * @param {Object}computedWidths column widths given by calculateColWidths()
270
+ * @param {integer[]}computedWidths.colWidth array of column widths
271
+ * @param {integer}colIndex slot colIndex. See {@link gridSlot#colIndex}
272
+ */
273
+ setSlotNodeWidth:function (slotNode, computedWidths, colIndex) {
274
+ var i, width = 0;
275
+ for (i = 0; i < slotNode.colSpan; i++) {
276
+ width += computedWidths.colWidth[colIndex + i];
277
+ }
278
+ slotNode.style.width = width + "px";
279
+ slotNode.style.maxWidth = width + "px";
280
+ },
281
+ /**
282
+ * Set slot height (the TD nodes)
283
+ * @param {HTMLElement}slotNode DOM node that maps slot element
284
+ * @param {Object}computedHeights column widths given by calculateRowHeights()
285
+ * @param {integer[]}computedHeights.rowHeight array of row heights
286
+ * @param {integer}rowIndex slot rowIndex. See {@link gridSlot#rowIndex}
287
+ */
288
+ setSlotNodeHeight:function (slotNode, computedHeights, rowIndex) {
289
+ var i, height = 0;
290
+ for (i = 0; i < slotNode.rowSpan; i++) {
291
+ height += computedHeights.rowHeight[rowIndex + i];
292
+ }
293
+ slotNode.style.overflow = "auto";
294
+
295
+ slotNode.childNodes[0].style.height = height + "px";
296
+ slotNode.childNodes[0].style.maxHeight = height + "px";
297
+ slotNode.childNodes[0].style.overflow = "auto";
298
+ },
299
+ /**
300
+ * Get DOM node that maps template grid (TABLE node)
301
+ * @param {HTMLElement}templateNode template node
302
+ * @returns {HTMLElement} templateNode.childNodes[0]
303
+ */
304
+ getGridNode:function (templateNode) {
305
+ return templateNode.childNodes[0];
306
+ },
307
+
308
+ /**
309
+ * Get DOM nodes that maps template grid "columns" (COL nodes)
310
+ * @param {HTMLElement}gridNode grid node
311
+ * @param {integer}maxColumns number of columns in grid
312
+ * @returns {HTMLElement[]} array of matching gridNode.childNodes[]
313
+ */
314
+ getColumnNodes:function (gridNode, maxColumns) {
315
+ var i, columnNodes = [];
316
+ for (i = 0; i < maxColumns; i++) {
317
+ columnNodes.push(gridNode.childNodes[i]);
318
+ }
319
+ return columnNodes;
320
+ },
321
+ /**
322
+ * Get DOM node that maps row (TR nodes)
323
+ * @param {HTMLElement}gridNode grid node
324
+ * @param {integer}index row index
325
+ * @param {integer}maxColumns number of columns in grid
326
+ * @returns {HTMLElement[]} array of matching gridNode.childNodes[]
327
+ */
328
+ getRowNode:function (gridNode, index, maxColumns) {
329
+ return gridNode.childNodes[maxColumns + index];
330
+ },
331
+ /**
332
+ * Get pixel size. Currently converts "px" and "%"
333
+ * @param {string}dimension source in "75[px|%]" format
334
+ * @param {integer}max max size in pixels. Only used relative sizes ("%")
335
+ * @returns {integer} given size converted to pixels or Error
336
+ */
337
+ getPixels:function (dimension, max) {
338
+ var found = dimension.match(/(\d+)(px|%)/);
339
+ if (found[2] === "%") {
340
+ return parseInt(found[1], 10) * max / 100;
341
+ }
342
+ if (found[2] === "px") {
343
+ return parseInt(found[1], 10);
344
+ }
345
+ },
346
+ /**
347
+ * A lightly modified version of "compute heights" algorithm defined in
348
+ * the draft.
349
+ * </p>
350
+ * The good parts, it works (thanks to native table algorithms);
351
+ * the bad, needs further improvements
352
+ *
353
+ * @param {template}template the source template
354
+ * @returns {ComputedHeight} rows height
355
+ */
356
+ computeRowHeights:function (template) {
357
+ /**
358
+ *
359
+ * @namespace Computed template rows heights
360
+ * @name ComputedHeight
361
+ */
362
+ var result =
363
+ /**
364
+ * @lends ComputedHeight#
365
+ */
366
+ {
367
+ /**
368
+ * Sum of rows heights
369
+ * @type integer
370
+ */
371
+ totalHeight:undefined,
372
+ /**
373
+ * Array of row heights
374
+ * @type integer[]
375
+ */
376
+ rowHeight:[]
377
+ }, tmp, height = 0, fixedHeights = 0, relativeHeights = 0;
378
+
379
+ tmp = template.grid.rows.map(function (row) {
380
+ if (/(\d+)(px)/.test(row.height)) {
381
+ return generator.fn.getPixels(row.height, 0);
382
+ }
383
+ return row.height;
384
+ }, this);
385
+
386
+ template.grid.rows.forEach(function (row, rowIndex) {
387
+ if (row.height === "*" || row.height === "auto") {
388
+ tmp[rowIndex] = 0;
389
+ row.slots.forEach(function (slot) {
390
+ if (slot.rowSpan === 1) {
391
+ var zzz = slot.htmlNode.clientHeight;
392
+ if (zzz > tmp[rowIndex]) {
393
+ tmp[rowIndex] = zzz;
394
+ }
395
+ }
396
+ }, this);
397
+ }
398
+ }, this);
399
+
400
+ template.grid.rows.forEach(function (row, rowIndex) {
401
+ if (row.height === "*") {
402
+ if (tmp[rowIndex] > height) {
403
+ height = tmp[rowIndex];
404
+ }
405
+ }
406
+ }, this);
407
+ template.grid.rows.forEach(function (row, rowIndex) {
408
+ if (row.height === "*") {
409
+ tmp[rowIndex] = height;
410
+ }
411
+ }, this);
412
+
413
+ tmp.forEach(function (height) {
414
+ if (/(\d+)(%)/.test(height)) {
415
+ var found = height.match(/(\d+)(%)/);
416
+ relativeHeights += parseInt(found[1], 10);
417
+ } else {
418
+ fixedHeights += height;
419
+ }
420
+ });
421
+ result.totalHeight = (fixedHeights * 100) / (100 - relativeHeights);
422
+ result.rowHeight = tmp;
423
+ return result;
424
+ },
425
+ /**
426
+ * A lightly modified version of "compute width" algorithm defined in
427
+ * the draft.
428
+ * </p>
429
+ * The good parts, it works (thanks to native table algorithms);
430
+ * the bad, needs further improvements
431
+ *
432
+ * @param {Number}availableWidth parent node max width
433
+ * @param {template}template the source template
434
+ * @returns {ComputedWidth} columns width
435
+ */
436
+ computeColWidths:function (availableWidth, template) {
437
+ /**
438
+ *
439
+ * @namespace Computed template columns widths
440
+ * @name ComputedWidth
441
+ * */
442
+ var result =
443
+ /**
444
+ * @lends ComputedWidth#
445
+ */
446
+ {
447
+ /**
448
+ * Sum of columns widths
449
+ * @type integer
450
+ */
451
+ totalWidth:undefined,
452
+ /**
453
+ * Array of columns widths
454
+ * @type integer[]
455
+ */
456
+ colWidth:[]
457
+ }, gridMinWidth, flexibleColCounter = 0, fixedColSum = 0, flexibleWidth = 0, gridFinalWidth = 0;
458
+
459
+
460
+ template.grid.widths.forEach(function (colWidth) {
461
+ if (colWidth === "*") {
462
+ flexibleColCounter++;
463
+ } else {
464
+ fixedColSum += generator.fn.getPixels(colWidth, availableWidth);
465
+ }
466
+ });
467
+ flexibleWidth = (flexibleColCounter > 0) ? (availableWidth - fixedColSum) / flexibleColCounter : 0;
468
+
469
+ gridMinWidth = template.grid.minWidths.reduce(function (previous, colMinWidth) {
470
+ return previous + generator.fn.getPixels(colMinWidth, availableWidth);
471
+ }, 0);
472
+
473
+ if (gridMinWidth > availableWidth) {
474
+ result.totalWidth = availableWidth;
475
+ result.colWidth = template.grid.minWidths.map(function (col) {
476
+ return generator.fn.getPixels(col, availableWidth);
477
+ });
478
+ } else {
479
+ result.colWidth = template.grid.widths.map(function (width) {
480
+ var tmp;
481
+ if (width === "*") {
482
+ gridFinalWidth += flexibleWidth;
483
+ return flexibleWidth;
484
+ }
485
+ if (/(\d+)(px|%)/.test(width)) {
486
+ //minWidth==width==preferredWidth
487
+ tmp = generator.fn.getPixels(width, availableWidth);
488
+ gridFinalWidth += tmp;
489
+ return tmp;
490
+ }
491
+ //no more use cases
492
+ });
493
+ result.totalWidth = gridFinalWidth;
494
+ }
495
+ return result;
496
+ },
497
+ /**
498
+ * Create the grid node (using TABLE) and inject it into parent node.
499
+ * Uses appendCol to create column nodes too.
500
+ * @param {grid} grid template grid
501
+ * @param {HTMLElement}parentNode DOM parent node
502
+ * @returns {HTMLElement} current node
503
+ */
504
+ appendGrid:function (grid, parentNode) {
505
+ var gridNode = document.createElement("table");
506
+ gridNode.className = "templateLayout templateLayoutTable";
507
+ parentNode.appendChild(gridNode);
508
+ generator.fn.appendCol(gridNode, grid.colNumber);
509
+ return gridNode;
510
+ },
511
+ /**
512
+ * Create columns nodes (using COL) and inject it into parent node
513
+ * @param {HTMLElement}parentNode DOM parent node
514
+ * @param {integer}colNumber max number of columns
515
+ * @returns {HTMLElement} current node
516
+ */
517
+ appendCol:function (parentNode, colNumber) {
518
+ var i, colNode;
519
+ for (i = 0; i < colNumber; i++) {
520
+ colNode = document.createElement("col");
521
+ colNode.className = "templateLayout templateLayoutCol";
522
+ parentNode.appendChild(colNode);
523
+ }
524
+ },
525
+ /**
526
+ * Create a row node (using TR) and inject it into parent node
527
+ * @param {gridRow}row template row
528
+ * @param {HTMLElement}parentNode DOM parent node
529
+ * @returns {HTMLElement} current node
530
+ */
531
+ appendRow:function (row, parentNode) {
532
+ var rowNode = document.createElement("tr");
533
+ rowNode.className = "templateLayout templateLayoutRow";
534
+ parentNode.appendChild(rowNode);
535
+ return rowNode;
536
+ },
537
+ /**
538
+ * Create a slot node (using TD) and inject it into parent node
539
+ * @param {gridSlot}slot template slot
540
+ * @param {HTMLElement}parentNode DOM parent node
541
+ * @returns {HTMLElement} current node
542
+ */
543
+ appendSlot:function (slot, parentNode) {
544
+ //create container
545
+ var cellNode, overflowNode;
546
+ cellNode = document.createElement("td");
547
+ cellNode.className = "templateLayout templateLayoutSlot";
548
+ slot.htmlNode = cellNode;
549
+ parentNode.appendChild(cellNode);
550
+
551
+ if (slot.rowSpan > 1) {
552
+ cellNode.rowSpan = slot.rowSpan;
553
+ }
554
+ if (slot.colSpan > 1) {
555
+ cellNode.colSpan = slot.colSpan;
556
+ }
557
+
558
+ overflowNode = document.createElement("div");
559
+ overflowNode.className = "templateLayout templateOverflow";
560
+ cellNode.appendChild(overflowNode);
561
+ return overflowNode;
562
+ },
563
+ /**
564
+ * Create a virtual node (using DIV) and inject it into parent node.
565
+ *
566
+ * Virtual nodes are valid templates that doesn't match selector queries
567
+ * because doesn´t have HTML content (used in nested templates chains).
568
+ * </p>
569
+ * <pre>
570
+ * #parent {display: "aa" "bc" "dd"}
571
+ * #header {position:a; display: "123"}
572
+ * #logo {position:1}
573
+ * ...
574
+ * &lt;div id="parent"&gt;&lt;/div&gt;
575
+ * &lt;img id="logo" src="logo.png"/&gt;
576
+ * ...
577
+ * </pre>
578
+ * #parent maps to DIV element and #logo to image, but #header maps
579
+ * nothing, its a template used only to simplify layout. #header needs
580
+ * to create a virtual node.
581
+ *
582
+ * @param {HTMLElement}parentNode DOM parent node
583
+ * @returns {HTMLElement} current node
584
+ */
585
+ appendVirtualNode:function (parentNode) {
586
+ var extraNode = document.createElement("div");
587
+ extraNode.className = "templateLayout templateLayoutVirtualNode";
588
+ parentNode.appendChild(extraNode);
589
+ return extraNode;
590
+ },
591
+ /**
592
+ * Get template node and inject it into parent node.
593
+ * Template node is get using a CSS selector query OR if query fails calling {@link generator#appendVirtualNode}
594
+ * @param {template}template the template
595
+ * @param {HTMLElement}parentNode DOM parent node
596
+ * @returns {HTMLElement} current node
597
+ */
598
+ appendTemplate:function (template, parentNode) {
599
+ var templateNode = document.querySelector(template.selectorText) || generator.fn.appendVirtualNode(parentNode);
600
+ template.htmlNode = templateNode;
601
+ if (templateNode.parentNode !== parentNode) {
602
+ parentNode.appendChild(templateNode);
603
+ }
604
+ return templateNode;
605
+ }
606
+ };
607
+
608
+ generator.fn = generator.prototype;
609
+ generator.prototype.init.prototype = generator.prototype;
610
+
611
+ templateLayout.fn.generator = generator;
612
+
613
+ log.info("generator module load... [OK]");
614
+
615
+ })(window.templateLayout);