more styling
[roojs1] / Roo / htmleditor / BlockTable.js
1  
2
3 /**
4  * @class Roo.htmleditor.BlockTable
5  * Block that manages a table
6  * 
7  * @constructor
8  * Create a new Filter.
9  * @param {Object} config Configuration options
10  */
11
12 Roo.htmleditor.BlockTable = function(cfg)
13 {
14     if (cfg.node) {
15         this.readElement(cfg.node);
16         this.updateElement(cfg.node);
17     }
18     Roo.apply(this, cfg);
19     if (!cfg.node) {
20         this.rows = [];
21         for(var r = 0; r < this.no_row; r++) {
22             this.rows[r] = [];
23             for(var c = 0; c < this.no_col; c++) {
24                 this.rows[r][c] = this.emptyCell();
25             }
26         }
27     }
28     
29     
30 }
31 Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
32  
33     rows : false,
34     no_col : 1,
35     no_row : 1,
36     
37     
38     width: '100%',
39     
40     // used by context menu
41     friendly_name : 'Table',
42     deleteTitle : 'Delete Table',
43     // context menu is drawn once..
44     
45     contextMenu : function(toolbar)
46     {
47         
48         var block = function() {
49             return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
50         };
51         
52         
53         var rooui =  typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
54         
55         var syncValue = toolbar.editorcore.syncValue;
56         
57         var fields = {};
58         
59         return [
60             {
61                 xtype : 'TextItem',
62                 text : "Width: ",
63                 xns : rooui.Toolbar  //Boostrap?
64             },
65             {
66                 xtype : 'ComboBox',
67                 allowBlank : false,
68                 displayField : 'val',
69                 editable : true,
70                 listWidth : 100,
71                 triggerAction : 'all',
72                 typeAhead : true,
73                 valueField : 'val',
74                 width : 100,
75                 name : 'width',
76                 listeners : {
77                     select : function (combo, r, index)
78                     {
79                         toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
80                         var b = block();
81                         b.width = r.get('val');
82                         b.updateElement();
83                         syncValue();
84                         toolbar.editorcore.onEditorEvent();
85                     }
86                 },
87                 xns : rooui.form,
88                 store : {
89                     xtype : 'SimpleStore',
90                     data : [
91                         ['100%'],
92                         ['auto']
93                     ],
94                     fields : [ 'val'],
95                     xns : Roo.data
96                 }
97             },
98             // -------- Cols
99             
100             {
101                 xtype : 'TextItem',
102                 text : "Columns: ",
103                 xns : rooui.Toolbar  //Boostrap?
104             },
105          
106             {
107                 xtype : 'Button',
108                 text: '-',
109                 listeners : {
110                     click : function (_self, e)
111                     {
112                         toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
113                         block().removeColumn();
114                         syncValue();
115                         toolbar.editorcore.onEditorEvent();
116                     }
117                 },
118                 xns : rooui.Toolbar
119             },
120             {
121                 xtype : 'Button',
122                 text: '+',
123                 listeners : {
124                     click : function (_self, e)
125                     {
126                         toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
127                         block().addColumn();
128                         syncValue();
129                         toolbar.editorcore.onEditorEvent();
130                     }
131                 },
132                 xns : rooui.Toolbar
133             },
134             // -------- ROWS
135             {
136                 xtype : 'TextItem',
137                 text : "Rows: ",
138                 xns : rooui.Toolbar  //Boostrap?
139             },
140          
141             {
142                 xtype : 'Button',
143                 text: '-',
144                 listeners : {
145                     click : function (_self, e)
146                     {
147                         toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
148                         block().removeRow();
149                         syncValue();
150                         toolbar.editorcore.onEditorEvent();
151                     }
152                 },
153                 xns : rooui.Toolbar
154             },
155             {
156                 xtype : 'Button',
157                 text: '+',
158                 listeners : {
159                     click : function (_self, e)
160                     {
161                         block().addRow();
162                         syncValue();
163                         toolbar.editorcore.onEditorEvent();
164                     }
165                 },
166                 xns : rooui.Toolbar
167             },
168             // -------- ROWS
169             {
170                 xtype : 'Button',
171                 text: 'Reset Column Widths',
172                 listeners : {
173                     
174                     click : function (_self, e)
175                     {
176                         block().resetWidths();
177                         syncValue();
178                         toolbar.editorcore.onEditorEvent();
179                     }
180                 },
181                 xns : rooui.Toolbar
182             } 
183             
184             
185             
186         ];
187         
188     },
189     
190     
191   /**
192      * create a DomHelper friendly object - for use with
193      * Roo.DomHelper.markup / overwrite / etc..
194      * ?? should it be called with option to hide all editing features?
195      */
196     toObject : function()
197     {
198         
199         var ret = {
200             tag : 'table',
201             contenteditable : 'false', // this stops cell selection from picking the table.
202             'data-block' : 'Table',
203             style : {
204                 width:  this.width,
205                 border : 'solid 1px #000', // ??? hard coded?
206                 'border-collapse' : 'collapse' 
207             },
208             cn : [
209                 { tag : 'tbody' , cn : [] }
210             ]
211         };
212         
213         // do we have a head = not really 
214         var ncols = 0;
215         Roo.each(this.rows, function( row ) {
216             var tr = {
217                 tag: 'tr',
218                 style : {
219                     margin: '6px',
220                     border : 'solid 1px #000',
221                     textAlign : 'left' 
222                 },
223                 cn : [ ]
224             };
225             
226             ret.cn[0].cn.push(tr);
227             // does the row have any properties? ?? height?
228             var nc = 0;
229             Roo.each(row, function( cell ) {
230                 
231                 var td = {
232                     tag : 'td',
233                     contenteditable :  'true',
234                     'data-block' : 'Td',
235                     html : cell.html,
236                     style : cell.style
237                 };
238                 if (cell.colspan > 1) {
239                     td.colspan = cell.colspan ;
240                     nc += cell.colspan;
241                 } else {
242                     nc++;
243                 }
244                 if (cell.rowspan > 1) {
245                     td.rowspan = cell.rowspan ;
246                 }
247                 
248                 
249                 // widths ?
250                 tr.cn.push(td);
251                     
252                 
253             }, this);
254             ncols = Math.max(nc, ncols);
255             
256             
257         }, this);
258         // add the header row..
259         
260         ncols++;
261          
262         
263         return ret;
264          
265     },
266     
267     readElement : function(node)
268     {
269         node  = node ? node : this.node ;
270         this.width = this.getVal(node, true, 'style', 'width') || '100%';
271         
272         this.rows = [];
273         this.no_row = 0;
274         var trs = Array.from(node.rows);
275         trs.forEach(function(tr) {
276             var row =  [];
277             this.rows.push(row);
278             
279             this.no_row++;
280             var no_column = 0;
281             Array.from(tr.cells).forEach(function(td) {
282                 
283                 var add = {
284                     colspan : td.hasAttribute('colspan') ? td.getAttribute('colspan')*1 : 1,
285                     rowspan : td.hasAttribute('rowspan') ? td.getAttribute('rowspan')*1 : 1,
286                     style : td.hasAttribute('style') ? td.getAttribute('style') : '',
287                     html : td.innerHTML
288                 };
289                 no_column += add.colspan;
290                      
291                 
292                 row.push(add);
293                 
294                 
295             },this);
296             this.no_col = Math.max(this.no_col, no_column);
297             
298             
299         },this);
300         
301         
302     },
303     normalizeRows: function()
304     {
305         var ret= [];
306         var rid = -1;
307         this.rows.forEach(function(row) {
308             rid++;
309             ret[rid] = [];
310             row = this.normalizeRow(row);
311             var cid = 0;
312             row.forEach(function(c) {
313                 while (typeof(ret[rid][cid]) != 'undefined') {
314                     cid++;
315                 }
316                 if (typeof(ret[rid]) == 'undefined') {
317                     ret[rid] = [];
318                 }
319                 ret[rid][cid] = c;
320                 c.row = rid;
321                 c.col = cid;
322                 if (c.rowspan < 2) {
323                     return;
324                 }
325                 
326                 for(var i = 1 ;i < c.rowspan; i++) {
327                     if (typeof(ret[rid+i]) == 'undefined') {
328                         ret[rid+i] = [];
329                     }
330                     ret[rid+i][cid] = c;
331                 }
332             });
333         }, this);
334         return ret;
335     
336     },
337     
338     normalizeRow: function(row)
339     {
340         var ret= [];
341         row.forEach(function(c) {
342             if (c.colspan < 2) {
343                 ret.push(c);
344                 return;
345             }
346             for(var i =0 ;i < c.colspan; i++) {
347                 ret.push(c);
348             }
349         });
350         return ret;
351     
352     },
353     
354     deleteColumn : function(sel)
355     {
356         if (!sel || sel.type != 'col') {
357             return;
358         }
359         if (this.no_col < 2) {
360             return;
361         }
362         
363         this.rows.forEach(function(row) {
364             var cols = this.normalizeRow(row);
365             var col = cols[sel.col];
366             if (col.colspan > 1) {
367                 col.colspan --;
368             } else {
369                 row.remove(col);
370             }
371             
372         }, this);
373         this.no_col--;
374         
375     },
376     removeColumn : function()
377     {
378         this.deleteColumn({
379             type: 'col',
380             col : this.no_col-1
381         });
382         this.updateElement();
383     },
384     
385      
386     addColumn : function()
387     {
388         
389         this.rows.forEach(function(row) {
390             row.push(this.emptyCell());
391            
392         }, this);
393         this.updateElement();
394     },
395     
396     deleteRow : function(sel)
397     {
398         if (!sel || sel.type != 'row') {
399             return;
400         }
401         
402         if (this.no_row < 2) {
403             return;
404         }
405         
406         var rows = this.normalizeRows();
407         
408         
409         rows[sel.row].forEach(function(col) {
410             if (col.rowspan > 1) {
411                 col.rowspan--;
412             } else {
413                 col.remove = 1; // flage it as removed.
414             }
415             
416         }, this);
417         var newrows = [];
418         this.rows.forEach(function(row) {
419             newrow = [];
420             row.forEach(function(c) {
421                 if (typeof(c.remove) == 'undefined') {
422                     newrow.push(c);
423                 }
424                 
425             });
426             if (newrow.length > 0) {
427                 newrows.push(row);
428             }
429         });
430         this.rows =  newrows;
431         
432         
433         
434         this.no_row--;
435         this.updateElement();
436         
437     },
438     removeRow : function()
439     {
440         this.deleteRow({
441             type: 'row',
442             row : this.no_row-1
443         });
444         
445     },
446     
447      
448     addRow : function()
449     {
450         
451         var row = [];
452         for (var i = 0; i < this.no_col; i++ ) {
453             
454             row.push(this.emptyCell());
455            
456         }
457         this.rows.push(row);
458         this.updateElement();
459         
460     },
461      
462     // the default cell object... at present...
463     emptyCell : function() {
464         return (new Roo.htmleditor.BlockTd({})).toObject();
465         
466      
467     },
468     
469     removeNode : function()
470     {
471         return this.node;
472     },
473     
474     
475     
476     resetWidths : function()
477     {
478         Array.from(this.node.getElementsByTagName('td')).forEach(function(n) {
479             var nn = Roo.htmleditor.Block.factory(n);
480             nn.width = '';
481             nn.updateElement(n);
482         });
483     }
484     
485     
486     
487     
488 })
489