5 * since selections really work on the table cell, then editing really should work from there
7 * The original plan was to support merging etc... - but that may not be needed yet..
9 * So this simple version will support:
11 * adjust the width +/-
21 * @class Roo.htmleditor.BlockTable
22 * Block that manages a table
25 * Create a new Filter.
26 * @param {Object} config Configuration options
29 Roo.htmleditor.BlockTd = function(cfg)
32 this.readElement(cfg.node);
33 this.updateElement(cfg.node);
40 Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
51 // used by context menu
52 friendly_name : 'Table Cell',
53 deleteTitle : 'Delete Table',
55 // context menu is drawn once..
57 contextMenu : function(toolbar)
60 var cell = function() {
61 return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
64 var table = function() {
65 return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode.closest('table'));
69 var saveSel = function()
71 lr = toolbar.editorcore.getSelection().getRangeAt(0);
73 var restoreSel = function()
77 toolbar.editorcore.focus();
78 var cr = toolbar.editorcore.getSelection();
81 toolbar.editorcore.onEditorEvent();
88 var rooui = typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
90 var syncValue = toolbar.editorcore.syncValue;
100 var t = toolbar.tb.selectedNode.closest('table');
101 toolbar.editorcore.selectNode(t);
102 toolbar.editorcore.onEditorEvent();
112 text : "Column Width: ",
120 click : function (_self, e)
122 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
123 cell().shrinkColumn();
125 toolbar.editorcore.onEditorEvent();
134 click : function (_self, e)
136 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
139 toolbar.editorcore.onEditorEvent();
146 text : "Merge Cells: ",
156 click : function (_self, e)
158 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
160 //block().growColumn();
162 toolbar.editorcore.onEditorEvent();
172 click : function (_self, e)
174 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
176 //block().growColumn();
178 toolbar.editorcore.onEditorEvent();
194 click : function (_self, e)
196 //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
199 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
200 toolbar.editorcore.onEditorEvent();
216 click : function (_self, e)
218 //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
221 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
222 toolbar.editorcore.onEditorEvent();
230 text: 'Delete Column',
232 click : function (_self, e)
234 //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
235 cell().deleteColumn();
237 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
238 toolbar.editorcore.onEditorEvent();
252 * create a DomHelper friendly object - for use with
253 * Roo.DomHelper.markup / overwrite / etc..
254 * ?? should it be called with option to hide all editing features?
257 * create a DomHelper friendly object - for use with
258 * Roo.DomHelper.markup / overwrite / etc..
259 * ?? should it be called with option to hide all editing features?
261 toObject : function()
266 contenteditable : 'true', // this stops cell selection from picking the table.
269 'text-align' : this.textAlign,
270 border : 'solid 1px rgb(0, 0, 0)', // ??? hard coded?
271 'border-collapse' : 'collapse',
272 padding : '6px' // 8 for desktop / 4 for mobile
276 if (this.width != '') {
277 ret.width = this.width;
278 ret.style.width = this.width;
282 if (this.colspan > 1) {
283 ret.colspan = this.colspan ;
285 if (this.rowspan > 1) {
286 ret.rowspan = this.rowspan ;
295 readElement : function(node)
297 node = node ? node : this.node ;
298 this.width = node.style.width;
299 this.colspan = Math.max(1,1*node.getAttribute('colspan'));
300 this.rowspan = Math.max(1,1*node.getAttribute('rowspan'));
301 this.html = node.innerHTML;
306 // the default cell object... at present...
307 emptyCell : function() {
312 html : " " // is this going to be editable now?
317 removeNode : function()
319 return this.node.closest('table');
327 toTableArray : function()
330 var tab = this.node.closest('tr').closest('table');
331 Array.from(tab.rows).forEach(function(r, ri){
337 Array.from(tab.rows).forEach(function(r, ri){
340 Array.from(r.cells).forEach(function(ce, ci){
345 colspan : ce.colSpan,
348 if (ce.isEqualNode(this.node)) {
351 // if we have been filled up by a row?
352 if (typeof(ret[rn][cn]) != 'undefined') {
353 while(typeof(ret[rn][cn]) != 'undefined') {
359 if (typeof(this.colWidths[cn]) == 'undefined') {
360 this.colWidths[cn] = ce.style.width;
361 if (this.colWidths[cn] != '') {
367 if (c.colspan < 2 && c.rowspan < 2 ) {
372 for(var j = 0; j < c.rowspan; j++) {
373 if (typeof(ret[rn+j]) == 'undefined') {
374 continue; // we have a problem..
377 for(var i = 0; i < c.colspan; i++) {
387 // initalize widths.?
388 // either all widths or no widths..
390 this.colWidths[0] = false; // no widths flag.
401 mergeRight: function()
404 // get the contents of the next cell along..
405 var tr = this.node.closest('tr');
406 var i = Array.prototype.indexOf.call(tr.childNodes, this.node);
407 if (i >= tr.childNodes.length - 1) {
408 return; // no cells on right to merge with.
410 var table = this.toTableArray();
412 if (typeof(table[this.cellData.row][this.cellData.col+this.cellData.colspan]) == 'undefined') {
413 return; // nothing right?
415 var rc = table[this.cellData.row][this.cellData.col+this.cellData.colspan];
416 // right cell - must be same rowspan and on the same row.
417 if (rc.rowspan != this.cellData.rowspan || rc.row != this.cellData.row) {
418 return; // right hand side is not same rowspan.
423 this.node.innerHTML += ' ' + rc.cell.innerHTML;
424 tr.removeChild(rc.cell);
425 this.colspan += rc.colspan;
426 this.node.setAttribute('colspan', this.colspan);
431 mergeBelow : function()
433 var table = this.toTableArray();
434 if (typeof(table[this.cellData.row+this.cellData.rowspan]) == 'undefined') {
435 return; // no row below
437 if (typeof(table[this.cellData.row+this.cellData.rowspan][this.cellData.col]) == 'undefined') {
438 return; // nothing right?
440 var rc = table[this.cellData.row+this.cellData.rowspan][this.cellData.col];
442 if (rc.colspan != this.cellData.colspan || rc.col != this.cellData.col) {
443 return; // right hand side is not same rowspan.
445 this.node.innerHTML = this.node.innerHTML + rc.cell.innerHTML ;
446 rc.cell.parentNode.removeChild(rc.cell);
447 this.rowspan += rc.rowspan;
448 this.node.setAttribute('rowspan', this.rowspan);
453 if (this.node.rowSpan < 2 && this.node.colSpan < 2) {
456 var table = this.toTableArray();
457 var cd = this.cellData;
461 for(var r = cd.row; r < cd.row + cd.rowspan; r++) {
465 for(var c = cd.col; c < cd.col + cd.colspan; c++) {
466 if (r == cd.row && c == cd.col) {
467 this.node.removeAttribute('rowspan');
468 this.node.removeAttribute('colspan');
472 var ntd = this.node.cloneNode(); // which col/row should be 0..
473 ntd.removeAttribute('id'); //
474 //ntd.style.width = '';
476 table[r][c] = { cell : ntd, col : c, row: r , colspan : 1 , rowspan : 1 };
480 this.redrawAllCells(table);
488 redrawAllCells: function(table)
492 var tab = this.node.closest('tr').closest('table');
493 Array.from(tab.rows).forEach(function(r, ri){
494 Array.from(r.cells).forEach(function(ce, ci){
495 ce.parentNode.removeChild(ce);
498 for(var r = 0 ; r < table.length; r++) {
499 var re = tab.rows[r];
500 for(var c = 0 ; c < table[r].length; c++) {
501 if (table[r][c].cell === false) {
505 re.appendChild(table[r][c].cell);
507 table[r][c].cell = false;
512 updateWidths : function(table)
514 for(var r = 0 ; r < table.length; r++) {
516 for(var c = 0 ; c < table[r].length; c++) {
517 if (table[r][c].cell === false) {
521 if (this.colWidths[0] != false && table[r][c].colspan < 2) {
522 var el = Roo.htmleditor.Block.factory(table[r][c].cell);
523 el.width = Math.floor(this.colWidths[c]) +'%';
524 el.updateElement(el.node);
526 table[r][c].cell = false; // done
530 normalizeWidths : function(table)
533 if (this.colWidths[0] === false) {
534 var nw = 100.0 / this.colWidths.length;
535 this.colWidths.forEach(function(w,i) {
536 this.colWidths[i] = nw;
541 var t = 0, missing = [];
543 this.colWidths.forEach(function(w,i) {
545 this.colWidths[i] = this.colWidths[i] == '' ? 0 : (this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;
546 var add = this.colWidths[i];
555 var nc = this.colWidths.length;
556 if (missing.length) {
557 var mult = (nc - missing.length) / (1.0 * nc);
559 var ew = (100 -t) / (1.0 * missing.length);
560 this.colWidths.forEach(function(w,i) {
562 this.colWidths[i] = w * mult;
566 this.colWidths[i] = ew;
568 // have to make up numbers..
571 // now we should have all the widths..
576 shrinkColumn : function()
578 var table = this.toTableArray();
579 this.normalizeWidths(table);
580 var col = this.cellData.col;
581 var nw = this.colWidths[col] * 0.8;
585 var otherAdd = (this.colWidths[col] * 0.2) / (this.colWidths.length -1);
586 this.colWidths.forEach(function(w,i) {
588 this.colWidths[i] = nw;
591 this.colWidths[i] += otherAdd
593 this.updateWidths(table);
596 growColumn : function()
598 var table = this.toTableArray();
599 this.normalizeWidths(table);
600 var col = this.cellData.col;
601 var nw = this.colWidths[col] * 1.2;
605 var otherSub = (this.colWidths[col] * 0.2) / (this.colWidths.length -1);
606 this.colWidths.forEach(function(w,i) {
608 this.colWidths[i] = nw;
611 this.colWidths[i] -= otherSub
613 this.updateWidths(table);
616 deleteRow : function()
618 // delete this rows 'tr'
619 // if any of the cells in this row have a rowspan > 1 && row!= this row..
620 // then reduce the rowspan.
621 var table = this.toTableArray();
622 // this.cellData.row;
623 for (var i =0;i< table[this.cellData.row].length ; i++) {
624 var c = table[this.cellData.row][i];
625 if (c.row != this.cellData.row) {
633 table.splice(this.cellData.row,1);
634 this.redrawAllCells(table);
637 deleteColumn : function()
639 var table = this.toTableArray();
640 // this.cellData.row;
641 for (var i =0;i< table.length ; i++) {
642 var c = table[i][this.cellData.col];
643 if (c.col != this.cellData.col) {
644 table[i][this.cellData.col].colspan--;
646 table[i].splice(this.cellData.col,1);
649 this.redrawAllCells(table);