flexlayout-rails 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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);