Merge branch 'master' of http://git.roojs.com/roobuilder
[roobuilder] / resources / roo.builder.js
1 //<script type="text/javascript">
2
3
4 // IPC: - via alert("IPC:{method}:{data}
5
6
7 var MODULE = { isBuilder : true };
8 // BC
9 var _this = MODULE;
10
11 // the apprenderer.
12 Builder  = {
13      
14     scriptTag : false,
15     
16     id : 1,
17
18
19   
20     saveHTML :  function( ) 
21         {
22             //print("TRAVERSE DOM?");
23             
24             var dom = document.body;
25             //print(dom);
26             var ret = '';
27             //Roo.select('body > div',true).each(function(el) {
28             // if the tree is not ready yet?
29             
30             
31             this.traverseDOMTree(function(s) { ret+=s; }, dom, 1);
32                 alert("IPC:SAVEHTML:" + ret);
33             return ret;
34         },
35         
36         
37         traverseDOMTree : function(cb, currentElement, depth) {
38             if (!currentElement ) {
39                 
40                 return;
41             }
42             //console.log(currentElement);
43             if (currentElement.className && currentElement.className.match(/roo-dynamic/)) {
44                 return;
45             }
46             
47             //Roo.log(currentElement);
48             var j;
49             var nodeName = currentElement.nodeName;
50             var tagName = currentElement.tagName;
51             
52             if  (nodeName == '#text') {
53                 cb(currentElement.nodeValue);
54                 return;
55             
56             }
57             if (nodeName.match(/^#/)) { // comments?
58                 return;
59             }
60              
61             
62             
63             if(nodeName == 'BR'){
64                 cb("<BR/>");
65                 return;
66             }
67             if (nodeName != 'BODY') {
68                 //Roo.log(currentElement);
69                 if (currentElement.hasAttribute('flexy:include')) {
70
71
72                     cb( '<flexy:include src="'+currentElement.getAttribute('flexy:include')+'"></flexy:include>');
73                     return;
74                 }
75             
76                 var i = 0;
77               // Prints the node tagName, such as <A>, <IMG>, etc
78                 if (tagName) {
79                     var attr = [];
80                     for(i = 0; i < currentElement.attributes.length;i++) {
81                         var attre = currentElement.attributes.item(i);
82                         var aname = attre.name;
83                         var aval = attre.value || '';
84                         if (aname=='id' && aval.match(/^roo\-/)) { // only roo -elements hide..
85                             aname= 'xbuilderid';
86                         }
87                         // skip -- component created by the builder?
88                         if (aval == 'builderel') { 
89                             return;
90                         }
91                         attr.push(aname + '="' + aval + '"' );  //?? escaping attributes?
92                     }
93                     
94                     
95                     cb("<"+currentElement.tagName+ ( attr.length ? (' ' + attr.join(' ') ) : '') + ">");
96                 } 
97                 else {
98                   cb("[unknown tag]");
99                 }
100             } else {
101                 tagName = false;
102             }
103             
104             
105             // Traverse the tree
106             i = 0;
107             var currentElementChild = currentElement.childNodes.item(i);
108             var allText = true;
109             while (currentElementChild) {
110                 // Formatting code (indent the tree so it looks nice on the screen)
111                 
112                 if  (currentElementChild.nodeName == '#text') {
113                     cb(currentElementChild.nodeValue);
114                     i++;
115                     currentElementChild=currentElement.childNodes.item(i);
116                     continue;
117                 }   
118                 allText = false;
119                 // if the current node is 'span' then all childre should not be indented..
120                 if (tagName != 'SPAN') {
121                     
122                     
123                     cb("\n");
124                     for (j = 0; j < depth; j++) {
125                       // &#166 is just a vertical line
126                       cb("  ");
127                     }               
128                 }    
129                     
130                 // Recursively traverse the tree structure of the child node
131                 this.traverseDOMTree(cb, currentElementChild, depth+1);
132                 i++;
133                 currentElementChild=currentElement.childNodes.item(i);
134             }
135             if (!allText && (tagName!= 'SPAN') ) {
136                     // The remaining code is mostly for formatting the tree
137                 cb("\n");
138                 for (j = 0; j < depth - 1; j++) {
139                   cb("  ");
140                 }     
141             }
142             if (tagName) {
143                 cb("</"+tagName+">");
144             }
145             
146         },
147
148
149         // this lot is to deal with draging // selecting? - not used at present
150         // 
151         
152      
153     findNode : function(ftg , method) {
154         if (!ftg) {
155             return  false;
156         }
157       // console.log(ftg.id);
158         if (ftg.id && typeof(ftg.id) == 'string' && ftg.id.match(/builder-/)) {
159             var nid = ftg.id.replace('builder-', '').replace('x-form-el-', '');
160             this[method]( nid );
161             return true;
162         }
163         // needs fixing..
164         if (ftg.dom.className.match(/[0-9]+/)) {
165             //console.log(ftg.dom.className);
166             var cmat = ftg.dom.className.match(/x-grid-hd-builder-(form-gen-[0-9:]+)/);
167             if (cmat) {
168                 this[method]( cmat[1] );
169                 return true;
170             }
171         }
172         
173         
174         
175         
176         return false;
177     },
178     
179     overPos: function(x,y) 
180     {
181         
182         var el = document.elementFromPoint(x,y);
183        // //console.log(el.id);
184        // console.log(document.body.innerHTML);
185         this.hover( {
186             getTarget : function () {
187                 return el;
188             },
189             stopEvent : function() {
190                 
191             }
192         });
193         
194         
195     },
196     onclick: function(e) {
197         var tg = Roo.get(e.getTarget());
198         if (!tg) {
199             //console.log('no target');
200             return;
201            }
202          
203         if (this.findNode(tg,'logClick')) {
204             return;
205         }
206         var dp = Roo.get(tg.up(''));
207         if (dp && this.findNode(dp,'logClick')) {
208             return;
209         }
210         
211         var ns = Roo.get(tg.getNextSibling());
212         if (ns && this.findNode(ns,'logClick')) {
213           
214             return;
215         }
216         if (ns && ns.down('') && this.findNode(Roo.get(ns.down('')) ,'logClick') ) {
217             return;
218         }
219         
220         for(var i =0; i < 5; i++) {
221             tg = Roo.get(tg.up(''));
222             if (!tg) {
223                 //console.log('no parent' + i);
224                 return;
225             }
226             if (tg && this.findNode(tg,'logClick')) {
227                 return;
228             }
229         }
230         //console.log('no target in parents');
231         
232     },
233     logClick : function(id) 
234     {
235          var bid = id.length ? 'builder-' + id : '';
236          console.log('{ "id" :  "' + bid + '"}');
237     },
238     
239     
240     hover : function(e) {
241         
242        
243         var tg = Roo.get(e.getTarget());
244         if (!tg) {
245             //console.log('no target');
246             this.logMove('');
247             return;
248            }
249          
250         if (this.findNode(tg,'logMove')) {
251             e.stopEvent();
252             return;
253         }
254         var dp = Roo.get(tg.up(''));
255         if (dp && this.findNode(dp,'logMove')) {
256             e.stopEvent();
257             return;
258         }
259         
260         var ns = Roo.get(tg.getNextSibling());
261         if (ns && this.findNode(ns,'logMove')) {
262             e.stopEvent();
263             return;
264         }
265         if (ns && ns.down('') && this.findNode(Roo.get(ns.down('')) ,'logMove' )) {
266             e.stopEvent();
267             return;
268         }
269         
270         for(var i =0; i < 5; i++) {
271             tg = Roo.get(tg.up(''));
272             if (!tg) {
273                 //console.log('no parent' + i);
274                 this.logMove('');
275                 return;
276             }
277             if (tg && this.findNode(tg,'logMove')) {
278                 e.stopEvent();
279                 return;
280             }
281         }
282         //console.log('no target in parents');
283         this.logMove('');
284     },
285     logMove : function (id) {
286         //console.log("LOGMOVE: " + id);
287         
288         if (this.lastID === id) {
289             return;
290        }
291        id = ''+ id;
292        var bid = id.length ? 'builder-' + id : '';
293        //console.log('{ "hover-node" :  "' + bid + '"}');
294        this.lastID = id;
295     },
296     clearBootstrap : function()
297     {
298         // if the page is not bootstrap
299         
300         if ( typeof(BuilderUseBootstrap) != 'undefined' ) {
301             Roo.log("it's boostrap - BuilderUseBootstrap is defined ");
302             // it's bootstrap - probably remove roo's css..
303             return;
304         }
305         Roo.log("remove css = BuilderUseBootstrap is not defined");
306         var rem = [];
307         var ar = document.getElementsByTagName('link');
308         for (var i = 0; i < ar.length;i++) {
309             var l = ar[i];
310             Roo.log(l.getAttribute('href'));
311             if (l.getAttribute('href').match(/bootstrap/)) {
312                 rem.push(l);
313                 
314                 
315             }
316             //code
317         }
318         Roo.each(rem, function(l) { l.parentNode.removeChild(l);});
319     },
320     
321     applyFlexy: function(tree)
322     {
323         if (!tree.el) {
324             return;
325         }
326         if (typeof(tree['flexy:foreach']) != 'undefined') {
327             //Roo.log("add flexy:foreach");
328             tree.el.attr('flexy:foreach', tree['flexy:foreach']);
329         }
330         if (typeof(tree['flexy:if']) != 'undefined') {
331             //Roo.log("add flexy:if");
332             tree.el.attr('flexy:if', tree['flexy:if']);
333         }
334         if (typeof(tree['xtype-bootstrap']) != 'undefined') {
335             //Roo.log("add flexy:if");
336             tree.el.attr('xtype', tree['xtype-bootstrap']);
337         }
338         
339         if (typeof(tree['flexy:include']) != 'undefined') {
340             //Roo.log("add flexy:if");
341             tree.el.attr('flexy:include', tree['flexy:include']);
342         }
343         
344         if (typeof(tree['flexy:ignore']) != 'undefined') {
345             //Roo.log("add flexy:if");
346             tree.el.attr('flexy:ignore', tree['flexy:ignore']);
347         }
348         
349         tree.el.attr('xtype', tree['|xns'] + '.' +  tree['xtype']);
350         //Roo.log(tree);
351         //Roo.log("Add xtype")
352          
353         
354         if (tree.items && tree.items.length > 0) { 
355         //Roo.log(tree);
356             for (var i = 0; i < tree.items.length; i++){
357                 this.applyFlexy(tree.items[i]);
358             }
359         }
360         if (typeof(tree.menu) == 'object') {
361             this.applyFlexy(tree.menu);
362         }
363         
364     }
365     
366      
367     
368 };
369 Roo.onReady(function() { Builder.clearBootstrap(); });
370 Roo.XComponent.on('buildcomplete', function() {
371     Roo.log("xcomponent built!");
372     var m = Roo.XComponent.modules;
373     Builder.applyFlexy(m[m.length-1].el);
374     
375         Builder.saveHTML.defer(100, Builder);
376 });