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, {
52 // used by context menu
53 friendly_name : 'Table Cell',
54 deleteTitle : false, // use our customer delete
56 // context menu is drawn once..
58 contextMenu : function(toolbar)
60 console.log("htmleditor.BlockTd contextMenu");
63 var cell = function() {
64 return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
67 var table = function() {
68 return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode.closest('table'));
72 var saveSel = function()
74 lr = toolbar.editorcore.getSelection().getRangeAt(0);
76 var restoreSel = function()
80 toolbar.editorcore.focus();
81 var cr = toolbar.editorcore.getSelection();
84 toolbar.editorcore.onEditorEvent();
91 var rooui = typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
93 var syncValue = toolbar.editorcore.syncValue;
103 var t = toolbar.tb.selectedNode.closest('table');
104 toolbar.editorcore.selectNode(t);
105 toolbar.editorcore.onEditorEvent();
115 text : "Column Width: ",
123 click : function (_self, e)
125 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
126 cell().shrinkColumn();
128 toolbar.editorcore.onEditorEvent();
137 click : function (_self, e)
139 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
142 toolbar.editorcore.onEditorEvent();
150 text : "Vertical Align: ",
151 xns : rooui.Toolbar //Boostrap?
156 displayField : 'val',
159 triggerAction : 'all',
165 select : function (combo, r, index)
167 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
169 b.valign = r.get('val');
172 toolbar.editorcore.onEditorEvent();
177 xtype : 'SimpleStore',
181 ['bottom'] // there are afew more...
190 text : "Merge Cells: ",
200 click : function (_self, e)
202 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
204 //block().growColumn();
206 toolbar.editorcore.onEditorEvent();
216 click : function (_self, e)
218 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
220 //block().growColumn();
222 toolbar.editorcore.onEditorEvent();
238 click : function (_self, e)
240 //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
243 toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
244 toolbar.editorcore.onEditorEvent();
270 click : function (_self, e)
274 cell().deleteColumn();
276 toolbar.editorcore.selectNode(t.node);
277 toolbar.editorcore.onEditorEvent();
286 click : function (_self, e)
292 toolbar.editorcore.selectNode(t.node);
293 toolbar.editorcore.onEditorEvent();
307 click : function (_self, e)
310 var nn = t.node.nextSibling || t.node.previousSibling;
311 t.node.parentNode.removeChild(t.node);
313 toolbar.editorcore.selectNode(nn, true);
315 toolbar.editorcore.onEditorEvent();
333 * create a DomHelper friendly object - for use with
334 * Roo.DomHelper.markup / overwrite / etc..
335 * ?? should it be called with option to hide all editing features?
338 * create a DomHelper friendly object - for use with
339 * Roo.DomHelper.markup / overwrite / etc..
340 * ?? should it be called with option to hide all editing features?
342 toObject : function()
344 console.log("htmleditor.BlockTd toObject");
347 contenteditable : 'true', // this stops cell selection from picking the table.
349 valign : this.valign,
351 'text-align' : this.textAlign,
352 border : 'solid 1px rgb(0, 0, 0)', // ??? hard coded?
353 'border-collapse' : 'collapse',
354 padding : '6px', // 8 for desktop / 4 for mobile
355 'vertical-align': this.valign
359 if (this.width != '') {
360 ret.width = this.width;
361 ret.style.width = this.width;
365 if (this.colspan > 1) {
366 ret.colspan = this.colspan ;
368 if (this.rowspan > 1) {
369 ret.rowspan = this.rowspan ;
378 readElement : function(node)
380 console.log("htmleditor.BlockTd readElement");
382 node = node ? node : this.node ;
383 this.width = node.style.width;
384 this.colspan = Math.max(1,1*node.getAttribute('colspan'));
385 this.rowspan = Math.max(1,1*node.getAttribute('rowspan'));
386 this.html = node.innerHTML;
391 // the default cell object... at present...
392 emptyCell : function() {
397 html : " " // is this going to be editable now?
402 removeNode : function()
404 return this.node.closest('table');
412 toTableArray : function()
414 console.log("htmleditor.BlockTd toTableArray");
416 var tab = this.node.closest('tr').closest('table');
417 Array.from(tab.rows).forEach(function(r, ri){
423 Array.from(tab.rows).forEach(function(r, ri){
426 Array.from(r.cells).forEach(function(ce, ci){
431 colspan : ce.colSpan,
434 if (ce.isEqualNode(this.node)) {
437 // if we have been filled up by a row?
438 if (typeof(ret[rn][cn]) != 'undefined') {
439 while(typeof(ret[rn][cn]) != 'undefined') {
445 if (typeof(this.colWidths[cn]) == 'undefined') {
446 this.colWidths[cn] = ce.style.width;
447 console.log("colWidths " + cn);
448 console.log(ce.style.width);
449 if (this.colWidths[cn] != '') {
455 if (c.colspan < 2 && c.rowspan < 2 ) {
460 for(var j = 0; j < c.rowspan; j++) {
461 if (typeof(ret[rn+j]) == 'undefined') {
462 continue; // we have a problem..
465 for(var i = 0; i < c.colspan; i++) {
475 // initalize widths.?
476 // either all widths or no widths..
478 this.colWidths[0] = false; // no widths flag.
489 mergeRight: function()
491 console.log("htmleditor.BlockTd mergeRight");
493 // get the contents of the next cell along..
494 var tr = this.node.closest('tr');
495 var i = Array.prototype.indexOf.call(tr.childNodes, this.node);
496 if (i >= tr.childNodes.length - 1) {
497 return; // no cells on right to merge with.
499 var table = this.toTableArray();
501 if (typeof(table[this.cellData.row][this.cellData.col+this.cellData.colspan]) == 'undefined') {
502 return; // nothing right?
504 var rc = table[this.cellData.row][this.cellData.col+this.cellData.colspan];
505 // right cell - must be same rowspan and on the same row.
506 if (rc.rowspan != this.cellData.rowspan || rc.row != this.cellData.row) {
507 return; // right hand side is not same rowspan.
512 this.node.innerHTML += ' ' + rc.cell.innerHTML;
513 tr.removeChild(rc.cell);
514 this.colspan += rc.colspan;
515 this.node.setAttribute('colspan', this.colspan);
520 mergeBelow : function()
522 var table = this.toTableArray();
523 if (typeof(table[this.cellData.row+this.cellData.rowspan]) == 'undefined') {
524 return; // no row below
526 if (typeof(table[this.cellData.row+this.cellData.rowspan][this.cellData.col]) == 'undefined') {
527 return; // nothing right?
529 var rc = table[this.cellData.row+this.cellData.rowspan][this.cellData.col];
531 if (rc.colspan != this.cellData.colspan || rc.col != this.cellData.col) {
532 return; // right hand side is not same rowspan.
534 this.node.innerHTML = this.node.innerHTML + rc.cell.innerHTML ;
535 rc.cell.parentNode.removeChild(rc.cell);
536 this.rowspan += rc.rowspan;
537 this.node.setAttribute('rowspan', this.rowspan);
542 if (this.node.rowSpan < 2 && this.node.colSpan < 2) {
545 var table = this.toTableArray();
546 var cd = this.cellData;
550 for(var r = cd.row; r < cd.row + cd.rowspan; r++) {
554 for(var c = cd.col; c < cd.col + cd.colspan; c++) {
555 if (r == cd.row && c == cd.col) {
556 this.node.removeAttribute('rowspan');
557 this.node.removeAttribute('colspan');
561 var ntd = this.node.cloneNode(); // which col/row should be 0..
562 ntd.removeAttribute('id'); //
563 //ntd.style.width = '';
565 table[r][c] = { cell : ntd, col : c, row: r , colspan : 1 , rowspan : 1 };
569 this.redrawAllCells(table);
577 redrawAllCells: function(table)
581 var tab = this.node.closest('tr').closest('table');
582 var ctr = tab.rows[0].parentNode;
583 Array.from(tab.rows).forEach(function(r, ri){
585 Array.from(r.cells).forEach(function(ce, ci){
586 ce.parentNode.removeChild(ce);
588 r.parentNode.removeChild(r);
590 for(var r = 0 ; r < table.length; r++) {
591 var re = tab.rows[r];
593 var re = tab.ownerDocument.createElement('tr');
595 for(var c = 0 ; c < table[r].length; c++) {
596 if (table[r][c].cell === false) {
600 re.appendChild(table[r][c].cell);
602 table[r][c].cell = false;
607 updateWidths : function(table)
609 for(var r = 0 ; r < table.length; r++) {
611 for(var c = 0 ; c < table[r].length; c++) {
612 if (table[r][c].cell === false) {
616 if (this.colWidths[0] != false && table[r][c].colspan < 2) {
617 var el = Roo.htmleditor.Block.factory(table[r][c].cell);
618 el.width = Math.floor(this.colWidths[c]) +'%';
619 el.updateElement(el.node);
621 table[r][c].cell = false; // done
625 normalizeWidths : function(table)
627 console.log("htmleditor.BlockTd normalizeWidths");
628 console.log("colWidths 0");
629 console.log(this.colWidths[0]);
630 console.log("colWidths 1");
631 console.log(this.colWidths[1]);
633 if (this.colWidths[0] === false) {
634 var nw = 100.0 / this.colWidths.length;
635 this.colWidths.forEach(function(w,i) {
636 this.colWidths[i] = nw;
641 var t = 0, missing = [];
643 this.colWidths.forEach(function(w,i) {
645 this.colWidths[i] = this.colWidths[i] == '' ? 0 : (this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;
646 var add = this.colWidths[i];
655 var nc = this.colWidths.length;
656 if (missing.length) {
657 var mult = (nc - missing.length) / (1.0 * nc);
659 var ew = (100 -t) / (1.0 * missing.length);
660 this.colWidths.forEach(function(w,i) {
662 this.colWidths[i] = w * mult;
666 this.colWidths[i] = ew;
668 // have to make up numbers..
671 // now we should have all the widths..
676 shrinkColumn : function()
678 console.log("htmleditor.BlockTd shrinkColumn");
679 var table = this.toTableArray();
681 this.normalizeWidths(table);
682 var col = this.cellData.col;
683 var nw = this.colWidths[col] * 0.8;
687 var otherAdd = (this.colWidths[col] * 0.2) / (this.colWidths.length -1);
688 this.colWidths.forEach(function(w,i) {
690 this.colWidths[i] = nw;
693 this.colWidths[i] += otherAdd
695 this.updateWidths(table);
698 growColumn : function()
700 console.log("htmleditor.BlockTd growColumn");
701 var table = this.toTableArray();
703 this.normalizeWidths(table);
704 var col = this.cellData.col;
705 var nw = this.colWidths[col] * 1.2;
709 var otherSub = (this.colWidths[col] * 0.2) / (this.colWidths.length -1);
710 this.colWidths.forEach(function(w,i) {
712 this.colWidths[i] = nw;
715 this.colWidths[i] -= otherSub
717 this.updateWidths(table);
720 deleteRow : function()
722 // delete this rows 'tr'
723 // if any of the cells in this row have a rowspan > 1 && row!= this row..
724 // then reduce the rowspan.
725 var table = this.toTableArray();
726 // this.cellData.row;
727 for (var i =0;i< table[this.cellData.row].length ; i++) {
728 var c = table[this.cellData.row][i];
729 if (c.row != this.cellData.row) {
732 c.cell.setAttribute('rowspan', c.rowspan);
737 c.cell.setAttribute('rowspan', c.rowspan);
740 table.splice(this.cellData.row,1);
741 this.redrawAllCells(table);
744 deleteColumn : function()
746 var table = this.toTableArray();
748 for (var i =0;i< table.length ; i++) {
749 var c = table[i][this.cellData.col];
750 if (c.col != this.cellData.col) {
751 table[i][this.cellData.col].colspan--;
752 } else if (c.colspan > 1) {
754 c.cell.setAttribute('colspan', c.colspan);
756 table[i].splice(this.cellData.col,1);
759 this.redrawAllCells(table);