Changeset 1064


Ignore:
Timestamp:
10/06/08 16:05:33 (11 years ago)
Author:
nicholasbs
Message:

Fix formatting/tabs (remove actual tabs, replace with 2-space indents)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/plugins/TableOperations/table-operations.js

    r1044 r1064  
    1515// Object that will encapsulate all the table operations provided by 
    1616// HTMLArea-3.0 (except "insert table" which is included in the main file) 
    17 Xinha.Config.prototype.TableOperations =  
    18 { 
     17Xinha.Config.prototype.TableOperations = { 
    1918  'showButtons' : true // Set to false to hide all but inserttable and toggleborders buttons on the toolbar 
    20                                            // this is useful if you have the ContextMenu plugin and want to save toolbar space 
    21                                            // (the context menu can perform all the button operations) 
     19  // this is useful if you have the ContextMenu plugin and want to save toolbar space 
     20  // (the context menu can perform all the button operations) 
    2221} 
    2322 
    2423function TableOperations(editor) { 
    25         this.editor = editor; 
    26  
    27         var cfg = editor.config; 
    28         var bl = TableOperations.btnList; 
    29         var self = this; 
    30  
    31         // register the toolbar buttons provided by this plugin 
     24  this.editor = editor; 
     25 
     26  var cfg = editor.config; 
     27  var bl = TableOperations.btnList; 
     28  var self = this; 
     29 
     30  // register the toolbar buttons provided by this plugin 
    3231 
    3332  // Remove existing inserttable and toggleborders, we will replace it in our group   
    3433  cfg.removeToolbarElement(' inserttable toggleborders ');  
    3534   
    36         var toolbar = ["linebreak", "inserttable", "toggleborders"]; 
    37          
    38    
    39         for (var i = 0; i < bl.length; ++i) { 
    40                 var btn = bl[i]; 
    41                 if (!btn) { 
    42                   if(cfg.TableOperations.showButtons)   toolbar.push("separator"); 
    43                 } else { 
    44                         var id = "TO-" + btn[0]; 
    45                         cfg.registerButton(id, Xinha._lc(btn[2], "TableOperations"), editor.imgURL(btn[0] + ".gif", "TableOperations"), false, 
    46                                            function(editor, id) { 
    47                                                    // dispatch button press event 
    48                                                    self.buttonPress(editor, id); 
    49                                            }, btn[1]); 
    50                         if(cfg.TableOperations.showButtons) toolbar.push(id); 
    51                 } 
    52         } 
    53    
    54  
    55         // add a new line in the toolbar 
    56         cfg.toolbar.push(toolbar); 
    57          
    58         if ( typeof PopupWin == 'undefined' ) 
     35  var toolbar = ["linebreak", "inserttable", "toggleborders"]; 
     36   
     37   
     38  for (var i = 0; i < bl.length; ++i) { 
     39    var btn = bl[i]; 
     40    if (!btn) { 
     41      if(cfg.TableOperations.showButtons) toolbar.push("separator"); 
     42    } else { 
     43      var id = "TO-" + btn[0]; 
     44      cfg.registerButton(id, Xinha._lc(btn[2], "TableOperations"), editor.imgURL(btn[0] + ".gif", "TableOperations"), false, 
     45                         function(editor, id) { 
     46                           // dispatch button press event 
     47                           self.buttonPress(editor, id); 
     48                         }, btn[1]); 
     49      if(cfg.TableOperations.showButtons) toolbar.push(id); 
     50    } 
     51  } 
     52   
     53 
     54  // add a new line in the toolbar 
     55  cfg.toolbar.push(toolbar); 
     56   
     57  if ( typeof PopupWin == 'undefined' ) 
    5958  { 
    60         Xinha._loadback(_editor_url + 'modules/Dialogs/popupwin.js'); 
    61   } 
    62         if ( typeof Xinha.InlineStyler == 'undefined' ) 
     59    Xinha._loadback(_editor_url + 'modules/Dialogs/popupwin.js'); 
     60  } 
     61  if ( typeof Xinha.InlineStyler == 'undefined' ) 
    6362  { 
    64         Xinha._loadback(_editor_url + 'modules/InlineStyler/InlineStyler.js'); 
    65   } 
    66          
     63    Xinha._loadback(_editor_url + 'modules/InlineStyler/InlineStyler.js'); 
     64  } 
     65   
    6766} 
    6867 
    6968TableOperations._pluginInfo = { 
    70         name          : "TableOperations", 
    71         version       : "1.0", 
    72         developer     : "Mihai Bazon", 
    73         developer_url : "http://dynarch.com/mishoo/", 
    74         c_owner       : "Mihai Bazon", 
    75         sponsor       : "Zapatec Inc.", 
    76         sponsor_url   : "http://www.bloki.com", 
    77         license       : "htmlArea" 
     69  name          : "TableOperations", 
     70  version       : "1.0", 
     71  developer     : "Mihai Bazon", 
     72  developer_url : "http://dynarch.com/mishoo/", 
     73  c_owner       : "Mihai Bazon", 
     74  sponsor       : "Zapatec Inc.", 
     75  sponsor_url   : "http://www.bloki.com", 
     76  license       : "htmlArea" 
    7877}; 
    7978 
    8079TableOperations.prototype._lc = function(string) { 
    81         return Xinha._lc(string, 'TableOperations'); 
     80  return Xinha._lc(string, 'TableOperations'); 
    8281}; 
    8382 
     
    8988// ancestors of the current selection/caret. 
    9089TableOperations.prototype.getClosest = function(tagName) { 
    91         var editor = this.editor; 
    92         var ancestors = editor.getAllAncestors(); 
    93         var ret = null; 
    94         tagName = ("" + tagName).toLowerCase(); 
    95         for (var i = 0; i < ancestors.length; ++i) { 
    96                 var el = ancestors[i]; 
    97                 if (el.tagName.toLowerCase() == tagName) { 
    98                         ret = el; 
    99                         break; 
    100                 } 
    101         } 
    102         return ret; 
     90  var editor = this.editor; 
     91  var ancestors = editor.getAllAncestors(); 
     92  var ret = null; 
     93  tagName = ("" + tagName).toLowerCase(); 
     94  for (var i = 0; i < ancestors.length; ++i) { 
     95    var el = ancestors[i]; 
     96    if (el.tagName.toLowerCase() == tagName) { 
     97      ret = el; 
     98      break; 
     99    } 
     100  } 
     101  return ret; 
    103102}; 
    104103 
     
    106105// was pressed. 
    107106TableOperations.prototype.buttonPress = function(editor, button_id) { 
    108         this.editor = editor; 
    109         var mozbr = Xinha.is_gecko ? "<br />" : ""; 
    110  
    111         // helper function that clears the content in a table row 
    112         function clearRow(tr) { 
    113                 var tds = tr.getElementsByTagName("td"); 
    114                 for (var i = tds.length; --i >= 0;) { 
    115                         var td = tds[i]; 
    116                         td.rowSpan = 1; 
    117                         td.innerHTML = mozbr; 
    118                 } 
    119         } 
    120  
    121         function splitRow(td) { 
    122                 var n = parseInt("" + td.rowSpan); 
    123                 var nc = parseInt("" + td.colSpan); 
    124                 td.rowSpan = 1; 
    125                 tr = td.parentNode; 
    126                 var itr = tr.rowIndex; 
    127                 var trs = tr.parentNode.rows; 
    128                 var index = td.cellIndex; 
    129                 while (--n > 0) { 
    130                         tr = trs[++itr]; 
    131                         var otd = editor._doc.createElement("td"); 
    132                         otd.colSpan = td.colSpan; 
    133                         otd.innerHTML = mozbr; 
    134                         tr.insertBefore(otd, tr.cells[index]); 
    135                 } 
    136                 editor.forceRedraw(); 
    137                 editor.updateToolbar(); 
    138         } 
    139  
    140         function splitCol(td) { 
    141                 var nc = parseInt("" + td.colSpan); 
    142                 td.colSpan = 1; 
    143                 tr = td.parentNode; 
    144                 var ref = td.nextSibling; 
    145                 while (--nc > 0) { 
    146                         var otd = editor._doc.createElement("td"); 
    147                         otd.rowSpan = td.rowSpan; 
    148                         otd.innerHTML = mozbr; 
    149                         tr.insertBefore(otd, ref); 
    150                 } 
    151                 editor.forceRedraw(); 
    152                 editor.updateToolbar(); 
    153         } 
    154  
    155         function splitCell(td) { 
    156                 var nc = parseInt("" + td.colSpan); 
    157                 splitCol(td); 
    158                 var items = td.parentNode.cells; 
    159                 var index = td.cellIndex; 
    160                 while (nc-- > 0) { 
    161                         splitRow(items[index++]); 
    162                 } 
    163         } 
    164  
    165         function selectNextNode(el) { 
    166                 var node = el.nextSibling; 
    167                 while (node && node.nodeType != 1) { 
    168                         node = node.nextSibling; 
    169                 } 
    170                 if (!node) { 
    171                         node = el.previousSibling; 
    172                         while (node && node.nodeType != 1) { 
    173                                 node = node.previousSibling; 
    174                         } 
    175                 } 
    176                 if (!node) { 
    177                         node = el.parentNode; 
    178                 } 
    179                 editor.selectNodeContents(node); 
    180         } 
    181  
    182         function cellMerge(table, cell_index, row_index, no_cols, no_rows) { 
    183                 var rows = []; 
    184                 var cells = []; 
    185                 try { 
    186                         for (i=row_index; i<row_index+no_rows; i++) { 
    187                                 var row = table.rows[i]; 
    188                                 for (j=cell_index; j<cell_index+no_cols; j++) { 
    189                                         if (row.cells[j].colSpan > 1 || row.cells[j].rowSpan > 1) { 
    190                                                 splitCell(row.cells[j]); 
    191                                         } 
    192                                         cells.push(row.cells[j]); 
    193                                 } 
    194                                 if (cells.length > 0) { 
    195                                         rows.push(cells); 
    196                                         cells = []; 
    197                                 } 
    198                         } 
    199                 } catch(e) {  
    200                         alert("Invalid selection"); 
    201                         return false; 
    202                 } 
    203                 var row_index1 = rows[0][0].parentNode.rowIndex; 
    204                 var row_index2 = rows[rows.length-1][0].parentNode.rowIndex; 
    205                 var row_span2 = rows[rows.length-1][0].rowSpan; 
    206                 var HTML = ""; 
    207                 for (i = 0; i < rows.length; ++i) { 
    208                         var cells = rows[i]; 
    209                         for (var j = 0; j < cells.length; ++j) { 
    210                                 var cell = cells[j]; 
    211                                 HTML += cell.innerHTML; 
    212                                 (i || j) && (cell.parentNode.removeChild(cell)); 
    213                         } 
    214                 } 
    215                 var td = rows[0][0]; 
    216                 td.innerHTML = HTML; 
    217                 td.rowSpan = row_index2 - row_index1 + row_span2; 
    218                 var col_span = 0; 
    219                 for(j=0; j<rows[0].length; j++) { 
    220                         col_span += rows[0][j].colSpan; 
    221                 } 
    222                 td.colSpan = col_span; 
    223                 editor.selectNodeContents(td); 
    224                 editor.forceRedraw(); 
    225                 editor.focusEditor(); 
    226         } 
    227  
    228         switch (button_id) { 
    229                 // ROWS 
    230  
    231                 case "TO-row-insert-above": 
    232                 case "TO-row-insert-under": 
    233                 var tr = this.getClosest("tr"); 
    234                 if (!tr) { 
    235                         break; 
    236                 } 
    237                 var otr = tr.cloneNode(true); 
    238                 clearRow(otr); 
    239                 tr.parentNode.insertBefore(otr, /under/.test(button_id) ? tr.nextSibling : tr); 
    240                 editor.forceRedraw(); 
    241                 editor.focusEditor(); 
    242                 break; 
    243                 case "TO-row-delete": 
    244                 var tr = this.getClosest("tr"); 
    245                 if (!tr) { 
    246                         break; 
    247                 } 
    248                 var par = tr.parentNode; 
    249                 if (par.rows.length == 1) { 
    250                         alert(Xinha._lc("Xinha cowardly refuses to delete the last row in table.", "TableOperations")); 
    251                         break; 
    252                 } 
    253                 // set the caret first to a position that doesn't 
    254                 // disappear. 
    255                 selectNextNode(tr); 
    256                 par.removeChild(tr); 
    257                 editor.forceRedraw(); 
    258                 editor.focusEditor(); 
    259                 editor.updateToolbar(); 
    260                 break; 
    261                 case "TO-row-split": 
    262                 var td = this.getClosest("td"); 
    263                 if (!td) { 
    264                         break; 
    265                 } 
    266                 splitRow(td); 
    267                 break; 
    268  
    269                 // COLUMNS 
    270  
    271                 case "TO-col-insert-before": 
    272                 case "TO-col-insert-after": 
    273                 var td = this.getClosest("td"); 
    274                 if (!td) { 
    275                         break; 
    276                 } 
    277                 var rows = td.parentNode.parentNode.rows; 
    278                 var index = td.cellIndex; 
    279         var lastColumn = (td.parentNode.cells.length == index + 1); 
    280                 for (var i = rows.length; --i >= 0;) { 
    281                         var tr = rows[i];                        
    282                         var otd = editor._doc.createElement("td"); 
    283                         otd.innerHTML = mozbr; 
    284           if (lastColumn && Xinha.is_ie)  
    285           { 
    286                 tr.insertBefore(otd); 
    287           }  
    288           else  
    289           { 
    290                 var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)]; 
    291                 tr.insertBefore(otd, ref); 
    292           } 
    293                 } 
    294                 editor.focusEditor(); 
    295                 break; 
    296                 case "TO-col-split": 
    297                 var td = this.getClosest("td"); 
    298                 if (!td) { 
    299                         break; 
    300                 } 
    301                 splitCol(td); 
    302                 break; 
    303                 case "TO-col-delete": 
    304                 var td = this.getClosest("td"); 
    305                 if (!td) { 
    306                         break; 
    307                 } 
    308                 var index = td.cellIndex; 
    309                 if (td.parentNode.cells.length == 1) { 
    310                         alert(Xinha._lc("Xinha cowardly refuses to delete the last column in table.", "TableOperations")); 
    311                         break; 
    312                 } 
    313                 // set the caret first to a position that doesn't disappear 
    314                 selectNextNode(td); 
    315                 var rows = td.parentNode.parentNode.rows; 
    316                 for (var i = rows.length; --i >= 0;) { 
    317                         var tr = rows[i]; 
    318                         tr.removeChild(tr.cells[index]); 
    319                 } 
    320                 editor.forceRedraw(); 
    321                 editor.focusEditor(); 
    322                 editor.updateToolbar(); 
    323                 break; 
    324  
    325                 // CELLS 
    326  
    327                 case "TO-cell-split": 
    328                 var td = this.getClosest("td"); 
    329                 if (!td) { 
    330                         break; 
    331                 } 
    332                 splitCell(td); 
    333                 break; 
    334                 case "TO-cell-insert-before": 
    335                 case "TO-cell-insert-after": 
    336                 var td = this.getClosest("td"); 
    337                 if (!td) { 
    338                         break; 
    339                 } 
    340                 var tr = td.parentNode; 
    341                 var otd = editor._doc.createElement("td"); 
    342                 otd.innerHTML = mozbr; 
    343                 tr.insertBefore(otd, /after/.test(button_id) ? td.nextSibling : td); 
    344                 editor.forceRedraw(); 
    345                 editor.focusEditor(); 
    346                 break; 
    347                 case "TO-cell-delete": 
    348                 var td = this.getClosest("td"); 
    349                 if (!td) { 
    350                         break; 
    351                 } 
    352                 if (td.parentNode.cells.length == 1) { 
    353                         alert(Xinha._lc("Xinha cowardly refuses to delete the last cell in row.", "TableOperations")); 
    354                         break; 
    355                 } 
    356                 // set the caret first to a position that doesn't disappear 
    357                 selectNextNode(td); 
    358                 td.parentNode.removeChild(td); 
    359                 editor.forceRedraw(); 
    360                 editor.updateToolbar(); 
    361                 break; 
    362                 case "TO-cell-merge": 
    363                 //Mozilla, as opposed to IE, allows the selection of several cells, which is fine :) 
    364                 var sel = editor._getSelection(); 
    365                 if (!Xinha.is_ie && sel.rangeCount > 1) { 
    366                         var range = sel.getRangeAt(0); 
    367                         var td = range.startContainer.childNodes[range.startOffset]; 
    368                         var tr = td.parentNode; 
    369                         var cell_index = td.cellIndex;           
    370                         var row_index = tr.rowIndex; 
    371                         var row_index2 = 0; 
    372                         var rownum = row_index; 
    373                         var no_cols = 0; 
    374                         var row_colspan = 0; 
    375                         var td2, tr2; 
    376                         for(i=0; i<sel.rangeCount; i++) { 
    377                                 range = sel.getRangeAt(i); 
    378                                         td2 = range.startContainer.childNodes[range.startOffset]; 
    379                                         tr2 = td2.parentNode;    
    380                                         if(tr2.rowIndex != rownum) { 
    381                                                 rownum = tr2.rowIndex; 
    382                                                 row_colspan = 0; 
    383                                         } 
    384                                         row_colspan += td2.colSpan; 
    385                                         if(row_colspan > no_cols) { 
    386                                                 no_cols = row_colspan; 
    387                                         } 
    388                                         if(tr2.rowIndex + td2.rowSpan - 1 > row_index2) { 
    389                                                 row_index2 = tr2.rowIndex + td2.rowSpan - 1; 
    390                                         } 
    391                                 } 
    392                         var no_rows = row_index2 - row_index + 1; 
    393                         var table = tr.parentNode; 
    394                         cellMerge(table, cell_index, row_index, no_cols, no_rows);  
    395                 } else { 
    396                         // Internet Explorer "browser" or not more than one cell selected in Moz 
    397                         var td = this.getClosest("td"); 
    398                         if (!td) { 
    399                                 alert(Xinha._lc("Please click into some cell", "TableOperations")); 
    400                                 break; 
    401                         } 
    402                         var tr = td.parentNode; 
    403                         var cell_index = td.cellIndex; 
    404                         var row_index = tr.rowIndex; 
    405                         // pass cellMerge and the indices so apply() can call cellMerge and know  
    406                         // what cell was selected when the dialog was opened 
    407                         this.dialogMerge(cellMerge, cell_index, row_index); 
    408                 } 
    409                 break; 
    410  
    411                 // PROPERTIES 
    412  
    413                 case "TO-table-prop": 
    414                 this.dialogTableProperties(); 
    415                 break; 
    416  
    417                 case "TO-row-prop": 
    418                 this.dialogRowCellProperties(false); 
    419                 break; 
    420  
    421                 case "TO-cell-prop": 
    422                 this.dialogRowCellProperties(true); 
    423                 break; 
    424  
    425                 default: 
    426                 alert("Button [" + button_id + "] not yet implemented"); 
    427         } 
     107  this.editor = editor; 
     108  var mozbr = Xinha.is_gecko ? "<br />" : ""; 
     109 
     110  // helper function that clears the content in a table row 
     111  function clearRow(tr) { 
     112    var tds = tr.getElementsByTagName("td"); 
     113    for (var i = tds.length; --i >= 0;) { 
     114      var td = tds[i]; 
     115      td.rowSpan = 1; 
     116      td.innerHTML = mozbr; 
     117    } 
     118  } 
     119 
     120  function splitRow(td) { 
     121    var n = parseInt("" + td.rowSpan); 
     122    var nc = parseInt("" + td.colSpan); 
     123    td.rowSpan = 1; 
     124    tr = td.parentNode; 
     125    var itr = tr.rowIndex; 
     126    var trs = tr.parentNode.rows; 
     127    var index = td.cellIndex; 
     128    while (--n > 0) { 
     129      tr = trs[++itr]; 
     130      var otd = editor._doc.createElement("td"); 
     131      otd.colSpan = td.colSpan; 
     132      otd.innerHTML = mozbr; 
     133      tr.insertBefore(otd, tr.cells[index]); 
     134    } 
     135    editor.forceRedraw(); 
     136    editor.updateToolbar(); 
     137  } 
     138 
     139  function splitCol(td) { 
     140    var nc = parseInt("" + td.colSpan); 
     141    td.colSpan = 1; 
     142    tr = td.parentNode; 
     143    var ref = td.nextSibling; 
     144    while (--nc > 0) { 
     145      var otd = editor._doc.createElement("td"); 
     146      otd.rowSpan = td.rowSpan; 
     147      otd.innerHTML = mozbr; 
     148      tr.insertBefore(otd, ref); 
     149    } 
     150    editor.forceRedraw(); 
     151    editor.updateToolbar(); 
     152  } 
     153 
     154  function splitCell(td) { 
     155    var nc = parseInt("" + td.colSpan); 
     156    splitCol(td); 
     157    var items = td.parentNode.cells; 
     158    var index = td.cellIndex; 
     159    while (nc-- > 0) { 
     160      splitRow(items[index++]); 
     161    } 
     162  } 
     163 
     164  function selectNextNode(el) { 
     165    var node = el.nextSibling; 
     166    while (node && node.nodeType != 1) { 
     167      node = node.nextSibling; 
     168    } 
     169    if (!node) { 
     170      node = el.previousSibling; 
     171      while (node && node.nodeType != 1) { 
     172        node = node.previousSibling; 
     173      } 
     174    } 
     175    if (!node) { 
     176      node = el.parentNode; 
     177    } 
     178    editor.selectNodeContents(node); 
     179  } 
     180 
     181  function cellMerge(table, cell_index, row_index, no_cols, no_rows) { 
     182    var rows = []; 
     183    var cells = []; 
     184    try { 
     185      for (i=row_index; i<row_index+no_rows; i++) { 
     186        var row = table.rows[i]; 
     187        for (j=cell_index; j<cell_index+no_cols; j++) { 
     188          if (row.cells[j].colSpan > 1 || row.cells[j].rowSpan > 1) { 
     189            splitCell(row.cells[j]); 
     190          } 
     191          cells.push(row.cells[j]); 
     192        } 
     193        if (cells.length > 0) { 
     194          rows.push(cells); 
     195          cells = []; 
     196        } 
     197      } 
     198    } catch(e) {  
     199      alert("Invalid selection"); 
     200      return false; 
     201    } 
     202    var row_index1 = rows[0][0].parentNode.rowIndex; 
     203    var row_index2 = rows[rows.length-1][0].parentNode.rowIndex; 
     204    var row_span2 = rows[rows.length-1][0].rowSpan; 
     205    var HTML = ""; 
     206    for (i = 0; i < rows.length; ++i) { 
     207      var cells = rows[i]; 
     208      for (var j = 0; j < cells.length; ++j) { 
     209        var cell = cells[j]; 
     210        HTML += cell.innerHTML; 
     211        (i || j) && (cell.parentNode.removeChild(cell)); 
     212      } 
     213    } 
     214    var td = rows[0][0]; 
     215    td.innerHTML = HTML; 
     216    td.rowSpan = row_index2 - row_index1 + row_span2; 
     217    var col_span = 0; 
     218    for(j=0; j<rows[0].length; j++) { 
     219      col_span += rows[0][j].colSpan; 
     220    } 
     221    td.colSpan = col_span; 
     222    editor.selectNodeContents(td); 
     223    editor.forceRedraw(); 
     224    editor.focusEditor(); 
     225  } 
     226 
     227  switch (button_id) { 
     228    // ROWS 
     229 
     230  case "TO-row-insert-above": 
     231  case "TO-row-insert-under": 
     232    var tr = this.getClosest("tr"); 
     233    if (!tr) { 
     234      break; 
     235    } 
     236    var otr = tr.cloneNode(true); 
     237    clearRow(otr); 
     238    tr.parentNode.insertBefore(otr, /under/.test(button_id) ? tr.nextSibling : tr); 
     239    editor.forceRedraw(); 
     240    editor.focusEditor(); 
     241    break; 
     242  case "TO-row-delete": 
     243    var tr = this.getClosest("tr"); 
     244    if (!tr) { 
     245      break; 
     246    } 
     247    var par = tr.parentNode; 
     248    if (par.rows.length == 1) { 
     249      alert(Xinha._lc("Xinha cowardly refuses to delete the last row in table.", "TableOperations")); 
     250      break; 
     251    } 
     252    // set the caret first to a position that doesn't 
     253    // disappear. 
     254    selectNextNode(tr); 
     255    par.removeChild(tr); 
     256    editor.forceRedraw(); 
     257    editor.focusEditor(); 
     258    editor.updateToolbar(); 
     259    break; 
     260  case "TO-row-split": 
     261    var td = this.getClosest("td"); 
     262    if (!td) { 
     263      break; 
     264    } 
     265    splitRow(td); 
     266    break; 
     267 
     268    // COLUMNS 
     269 
     270  case "TO-col-insert-before": 
     271  case "TO-col-insert-after": 
     272    var td = this.getClosest("td"); 
     273    if (!td) { 
     274      break; 
     275    } 
     276    var rows = td.parentNode.parentNode.rows; 
     277    var index = td.cellIndex; 
     278    var lastColumn = (td.parentNode.cells.length == index + 1); 
     279    for (var i = rows.length; --i >= 0;) { 
     280      var tr = rows[i]; 
     281      var otd = editor._doc.createElement("td"); 
     282      otd.innerHTML = mozbr; 
     283      if (lastColumn && Xinha.is_ie)  
     284      { 
     285        tr.insertBefore(otd); 
     286      }  
     287      else  
     288      { 
     289        var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)]; 
     290        tr.insertBefore(otd, ref); 
     291      } 
     292    } 
     293    editor.focusEditor(); 
     294    break; 
     295  case "TO-col-split": 
     296    var td = this.getClosest("td"); 
     297    if (!td) { 
     298      break; 
     299    } 
     300    splitCol(td); 
     301    break; 
     302  case "TO-col-delete": 
     303    var td = this.getClosest("td"); 
     304    if (!td) { 
     305      break; 
     306    } 
     307    var index = td.cellIndex; 
     308    if (td.parentNode.cells.length == 1) { 
     309      alert(Xinha._lc("Xinha cowardly refuses to delete the last column in table.", "TableOperations")); 
     310      break; 
     311    } 
     312    // set the caret first to a position that doesn't disappear 
     313    selectNextNode(td); 
     314    var rows = td.parentNode.parentNode.rows; 
     315    for (var i = rows.length; --i >= 0;) { 
     316      var tr = rows[i]; 
     317      tr.removeChild(tr.cells[index]); 
     318    } 
     319    editor.forceRedraw(); 
     320    editor.focusEditor(); 
     321    editor.updateToolbar(); 
     322    break; 
     323 
     324    // CELLS 
     325 
     326  case "TO-cell-split": 
     327    var td = this.getClosest("td"); 
     328    if (!td) { 
     329      break; 
     330    } 
     331    splitCell(td); 
     332    break; 
     333  case "TO-cell-insert-before": 
     334  case "TO-cell-insert-after": 
     335    var td = this.getClosest("td"); 
     336    if (!td) { 
     337      break; 
     338    } 
     339    var tr = td.parentNode; 
     340    var otd = editor._doc.createElement("td"); 
     341    otd.innerHTML = mozbr; 
     342    tr.insertBefore(otd, /after/.test(button_id) ? td.nextSibling : td); 
     343    editor.forceRedraw(); 
     344    editor.focusEditor(); 
     345    break; 
     346  case "TO-cell-delete": 
     347    var td = this.getClosest("td"); 
     348    if (!td) { 
     349      break; 
     350    } 
     351    if (td.parentNode.cells.length == 1) { 
     352      alert(Xinha._lc("Xinha cowardly refuses to delete the last cell in row.", "TableOperations")); 
     353      break; 
     354    } 
     355    // set the caret first to a position that doesn't disappear 
     356    selectNextNode(td); 
     357    td.parentNode.removeChild(td); 
     358    editor.forceRedraw(); 
     359    editor.updateToolbar(); 
     360    break; 
     361  case "TO-cell-merge": 
     362    //Mozilla, as opposed to IE, allows the selection of several cells, which is fine :) 
     363    var sel = editor._getSelection(); 
     364    if (!Xinha.is_ie && sel.rangeCount > 1) { 
     365      var range = sel.getRangeAt(0); 
     366      var td = range.startContainer.childNodes[range.startOffset]; 
     367      var tr = td.parentNode; 
     368      var cell_index = td.cellIndex; 
     369      var row_index = tr.rowIndex; 
     370      var row_index2 = 0; 
     371      var rownum = row_index; 
     372      var no_cols = 0; 
     373      var row_colspan = 0; 
     374      var td2, tr2; 
     375      for(i=0; i<sel.rangeCount; i++) { 
     376        range = sel.getRangeAt(i); 
     377        td2 = range.startContainer.childNodes[range.startOffset]; 
     378        tr2 = td2.parentNode; 
     379        if(tr2.rowIndex != rownum) { 
     380          rownum = tr2.rowIndex; 
     381          row_colspan = 0; 
     382        } 
     383        row_colspan += td2.colSpan; 
     384        if(row_colspan > no_cols) { 
     385          no_cols = row_colspan; 
     386        } 
     387        if(tr2.rowIndex + td2.rowSpan - 1 > row_index2) { 
     388          row_index2 = tr2.rowIndex + td2.rowSpan - 1; 
     389        } 
     390      } 
     391      var no_rows = row_index2 - row_index + 1; 
     392      var table = tr.parentNode; 
     393      cellMerge(table, cell_index, row_index, no_cols, no_rows);  
     394    } else { 
     395      // Internet Explorer "browser" or not more than one cell selected in Moz 
     396      var td = this.getClosest("td"); 
     397      if (!td) { 
     398        alert(Xinha._lc("Please click into some cell", "TableOperations")); 
     399        break; 
     400      } 
     401      var tr = td.parentNode; 
     402      var cell_index = td.cellIndex; 
     403      var row_index = tr.rowIndex; 
     404      // pass cellMerge and the indices so apply() can call cellMerge and know  
     405      // what cell was selected when the dialog was opened 
     406      this.dialogMerge(cellMerge, cell_index, row_index); 
     407    } 
     408    break; 
     409 
     410    // PROPERTIES 
     411 
     412  case "TO-table-prop": 
     413    this.dialogTableProperties(); 
     414    break; 
     415 
     416  case "TO-row-prop": 
     417    this.dialogRowCellProperties(false); 
     418    break; 
     419 
     420  case "TO-cell-prop": 
     421    this.dialogRowCellProperties(true); 
     422    break; 
     423 
     424  default: 
     425    alert("Button [" + button_id + "] not yet implemented"); 
     426  } 
    428427}; 
    429428 
    430429// the list of buttons added by this plugin 
    431430TableOperations.btnList = [ 
    432         // table properties button 
    433         ["table-prop",       "table", "Table properties"], 
    434         null,                   // separator 
    435  
    436         // ROWS 
    437         ["row-prop",         "tr", "Row properties"], 
    438         ["row-insert-above", "tr", "Insert row before"], 
    439         ["row-insert-under", "tr", "Insert row after"], 
    440         ["row-delete",       "tr", "Delete row"], 
    441         ["row-split",        "td[rowSpan!=1]", "Split row"], 
    442         null, 
    443  
    444         // COLS 
    445         ["col-insert-before", "td", "Insert column before"], 
    446         ["col-insert-after",  "td", "Insert column after"], 
    447         ["col-delete",        "td", "Delete column"], 
    448         ["col-split",         "td[colSpan!=1]", "Split column"], 
    449         null, 
    450  
    451         // CELLS 
    452         ["cell-prop",          "td", "Cell properties"], 
    453         ["cell-insert-before", "td", "Insert cell before"], 
    454         ["cell-insert-after",  "td", "Insert cell after"], 
    455         ["cell-delete",        "td", "Delete cell"], 
    456         ["cell-merge",         "tr", "Merge cells"], 
    457         ["cell-split",         "td[colSpan!=1,rowSpan!=1]", "Split cell"] 
    458         ]; 
     431  // table properties button 
     432  ["table-prop",       "table", "Table properties"], 
     433  null, // separator 
     434 
     435  // ROWS 
     436  ["row-prop",         "tr", "Row properties"], 
     437  ["row-insert-above", "tr", "Insert row before"], 
     438  ["row-insert-under", "tr", "Insert row after"], 
     439  ["row-delete",       "tr", "Delete row"], 
     440  ["row-split",        "td[rowSpan!=1]", "Split row"], 
     441  null, 
     442 
     443  // COLS 
     444  ["col-insert-before", "td", "Insert column before"], 
     445  ["col-insert-after",  "td", "Insert column after"], 
     446  ["col-delete",        "td", "Delete column"], 
     447  ["col-split",         "td[colSpan!=1]", "Split column"], 
     448  null, 
     449 
     450  // CELLS 
     451  ["cell-prop",          "td", "Cell properties"], 
     452  ["cell-insert-before", "td", "Insert cell before"], 
     453  ["cell-insert-after",  "td", "Insert cell after"], 
     454  ["cell-delete",        "td", "Delete cell"], 
     455  ["cell-merge",         "tr", "Merge cells"], 
     456  ["cell-split",         "td[colSpan!=1,rowSpan!=1]", "Split cell"] 
     457]; 
    459458 
    460459TableOperations.prototype.dialogMerge = function(merge_func, cell_index, row_index) { 
     
    489488TableOperations.prototype.dialogTableProperties = function() { 
    490489 
    491         var table = this.getClosest("table"); 
    492         var self = this; 
    493         var editor = this.editor; 
    494  
    495         if(!this.dialogTablePropertiesHtml){ // retrieve the raw dialog contents 
    496                 Xinha._getback( Xinha.getPluginDir("TableOperations") + '/popups/dialogTable.html', function(getback) { self.dialogTablePropertiesHtml = getback; self.dialogTableProperties(); }); 
    497                 return; 
    498         } 
    499         if (!this.dialogTable) { 
    500                 // Now we have everything we need, so we can build the dialog. 
    501                 this.dialogTable = new Xinha.Dialog(editor, this.dialogTablePropertiesHtml, 'TableOperations',{width:440}) 
    502                 this.dialogTable.getElementById('cancel').onclick = function() { self.dialogTable.hide()}; 
    503         } 
    504         var dialog = this.dialogTable; 
    505          
    506         var Styler = new Xinha.InlineStyler(table, this.editor); 
    507          
    508         function apply() { 
    509                 var params = dialog.hide(); 
    510                 Styler.applyStyle(params); 
    511                  
    512                 for (var i in params) { 
    513           if(typeof params[i] == 'function') continue; 
    514                         var val = params[i]; 
    515                         if (typeof val == 'object' && val.tagName) val = val.value; 
    516                         switch (i) { 
    517                                 case "caption": 
    518                                 if (/\S/.test(val)) { 
    519                                         // contains non white-space characters 
    520                                         var caption = table.getElementsByTagName("caption")[0]; 
    521                                         if (!caption) { 
    522                                                 caption = dialog.editor._doc.createElement("caption"); 
    523                                                 table.insertBefore(caption, table.firstChild); 
    524                                         } 
    525                                         caption.innerHTML = val; 
    526                                 } else { 
    527                                         // search for caption and delete it if found 
    528                                         var caption = table.getElementsByTagName("caption")[0]; 
    529                                         if (caption) { 
    530                                                 caption.parentNode.removeChild(caption); 
    531                                         } 
    532                                 } 
    533                                 break; 
    534                                 case "summary": 
    535                                 table.summary = val; 
    536                                 break; 
    537                                 case "width": 
    538                                 table.style.width = ("" + val) + params.f_unit; 
    539                                 break; 
    540                                 case "align": 
    541                                 table.align = val; 
    542                                 break; 
    543                                 case "spacing": 
    544                                 table.cellSpacing = val; 
    545                                 break; 
    546                                 case "padding": 
    547                                 table.cellPadding = val; 
    548                                 break; 
    549                                 case "borders": 
    550                                 table.border = val; 
    551                                 break; 
    552                                 case "frames": 
    553                                 table.frame = val; 
    554                                 break; 
    555                                 case "rules": 
    556                                 table.rules = val; 
    557                                 break; 
    558                         } 
    559                 } 
    560  
    561                 // various workarounds to refresh the table display (Gecko, 
    562                 // what's going on?! do not disappoint me!) 
    563                 self.editor.forceRedraw(); 
    564                 self.editor.focusEditor(); 
    565                 self.editor.updateToolbar(); 
    566                 var save_collapse = table.style.borderCollapse; 
    567                 table.style.borderCollapse = "collapse"; 
    568                 table.style.borderCollapse = "separate"; 
    569                 table.style.borderCollapse = save_collapse; 
    570         } 
    571          
    572         var st_layout = Styler.createStyleLayoutFieldset(); 
    573         var p = dialog.getElementById("TO_layout"); 
    574         p.replaceChild(st_layout,p.firstChild); 
    575          
    576         var st_prop = Styler.createStyleFieldset(); 
    577         p = dialog.getElementById("TO_style"); 
    578         p.replaceChild(st_prop,p.firstChild); 
    579  
    580         this.dialogTable.getElementById('ok').onclick = apply; 
    581  
    582         // gather element's values 
    583         var values = {}; 
    584         var capel = table.getElementsByTagName("caption")[0]; 
    585         if (capel) { 
    586                 values['caption'] = capel.innerHTML; 
    587         } 
    588         else values['caption'] = ""; 
    589         values['summary'] = table.summary; 
    590          
    591         values['spacing'] = table.cellSpacing; 
    592         values['padding'] = table.cellPadding; 
    593         var f_borders = table.border; 
    594          
    595         values['frames'] = table.frame; 
    596         values['rules'] = table.rules; 
    597          
    598         this.dialogTable.show(values); 
     490  var table = this.getClosest("table"); 
     491  var self = this; 
     492  var editor = this.editor; 
     493 
     494  if(!this.dialogTablePropertiesHtml){ // retrieve the raw dialog contents 
     495    Xinha._getback( Xinha.getPluginDir("TableOperations") + '/popups/dialogTable.html', function(getback) { self.dialogTablePropertiesHtml = getback; self.dialogTableProperties(); }); 
     496    return; 
     497  } 
     498  if (!this.dialogTable) { 
     499    // Now we have everything we need, so we can build the dialog. 
     500    this.dialogTable = new Xinha.Dialog(editor, this.dialogTablePropertiesHtml, 'TableOperations',{width:440}) 
     501    this.dialogTable.getElementById('cancel').onclick = function() { self.dialogTable.hide()}; 
     502  } 
     503  var dialog = this.dialogTable; 
     504   
     505  var Styler = new Xinha.InlineStyler(table, this.editor); 
     506   
     507  function apply() { 
     508    var params = dialog.hide(); 
     509    Styler.applyStyle(params); 
     510     
     511    for (var i in params) { 
     512      if(typeof params[i] == 'function') continue; 
     513      var val = params[i]; 
     514      if (typeof val == 'object' && val.tagName) val = val.value; 
     515      switch (i) { 
     516      case "caption": 
     517        if (/\S/.test(val)) { 
     518          // contains non white-space characters 
     519          var caption = table.getElementsByTagName("caption")[0]; 
     520          if (!caption) { 
     521            caption = dialog.editor._doc.createElement("caption"); 
     522            table.insertBefore(caption, table.firstChild); 
     523          } 
     524          caption.innerHTML = val; 
     525        } else { 
     526          // search for caption and delete it if found 
     527          var caption = table.getElementsByTagName("caption")[0]; 
     528          if (caption) { 
     529            caption.parentNode.removeChild(caption); 
     530          } 
     531        } 
     532        break; 
     533      case "summary": 
     534        table.summary = val; 
     535        break; 
     536      case "width": 
     537        table.style.width = ("" + val) + params.f_unit; 
     538        break; 
     539      case "align": 
     540        table.align = val; 
     541        break; 
     542      case "spacing": 
     543        table.cellSpacing = val; 
     544        break; 
     545      case "padding": 
     546        table.cellPadding = val; 
     547        break; 
     548      case "borders": 
     549        table.border = val; 
     550        break; 
     551      case "frames": 
     552        table.frame = val; 
     553        break; 
     554      case "rules": 
     555        table.rules = val; 
     556        break; 
     557      } 
     558    } 
     559 
     560    // various workarounds to refresh the table display (Gecko, 
     561    // what's going on?! do not disappoint me!) 
     562    self.editor.forceRedraw(); 
     563    self.editor.focusEditor(); 
     564    self.editor.updateToolbar(); 
     565    var save_collapse = table.style.borderCollapse; 
     566    table.style.borderCollapse = "collapse"; 
     567    table.style.borderCollapse = "separate"; 
     568    table.style.borderCollapse = save_collapse; 
     569  } 
     570   
     571  var st_layout = Styler.createStyleLayoutFieldset(); 
     572  var p = dialog.getElementById("TO_layout"); 
     573  p.replaceChild(st_layout,p.firstChild); 
     574   
     575  var st_prop = Styler.createStyleFieldset(); 
     576  p = dialog.getElementById("TO_style"); 
     577  p.replaceChild(st_prop,p.firstChild); 
     578 
     579  this.dialogTable.getElementById('ok').onclick = apply; 
     580 
     581  // gather element's values 
     582  var values = {}; 
     583  var capel = table.getElementsByTagName("caption")[0]; 
     584  if (capel) { 
     585    values['caption'] = capel.innerHTML; 
     586  } 
     587  else values['caption'] = ""; 
     588  values['summary'] = table.summary; 
     589   
     590  values['spacing'] = table.cellSpacing; 
     591  values['padding'] = table.cellPadding; 
     592  var f_borders = table.border; 
     593   
     594  values['frames'] = table.frame; 
     595  values['rules'] = table.rules; 
     596   
     597  this.dialogTable.show(values); 
    599598}; 
    600599 
    601600TableOperations.prototype.dialogRowCellProperties = function(cell) { 
    602         // retrieve existing values 
    603         var element = this.getClosest(cell ? "td" : "tr"); 
    604         var table = this.getClosest("table"); 
    605  
    606         var self = this; 
    607         var editor = this.editor; 
    608  
    609         if(!self.dialogRowCellPropertiesHtml) // retrieve the raw dialog contents 
    610         { 
    611                 Xinha._getback( Xinha.getPluginDir("TableOperations") + '/popups/dialogRowCell.html', function(getback) { self.dialogRowCellPropertiesHtml = getback; self.dialogRowCellProperties(cell); }); 
    612                 return; 
    613         } 
    614         if (!this.dialogRowCell) { 
    615                 // Now we have everything we need, so we can build the dialog. 
    616                 this.dialogRowCell = new Xinha.Dialog(editor, self.dialogRowCellPropertiesHtml, 'TableOperations',{width:440}) 
    617                 this.dialogRowCell.getElementById('cancel').onclick = function() { self.dialogRowCell.hide()}; 
    618         } 
    619          
    620         var dialog = this.dialogRowCell; 
    621         dialog.getElementById('title').innerHTML = cell ? Xinha._lc("Cell Properties", "TableOperations") : Xinha._lc("Row Properties", "TableOperations"); 
     601  // retrieve existing values 
     602  var element = this.getClosest(cell ? "td" : "tr"); 
     603  var table = this.getClosest("table"); 
     604 
     605  var self = this; 
     606  var editor = this.editor; 
     607 
     608  if(!self.dialogRowCellPropertiesHtml) // retrieve the raw dialog contents 
     609  { 
     610    Xinha._getback( Xinha.getPluginDir("TableOperations") + '/popups/dialogRowCell.html', function(getback) { self.dialogRowCellPropertiesHtml = getback; self.dialogRowCellProperties(cell); }); 
     611    return; 
     612  } 
     613  if (!this.dialogRowCell) { 
     614    // Now we have everything we need, so we can build the dialog. 
     615    this.dialogRowCell = new Xinha.Dialog(editor, self.dialogRowCellPropertiesHtml, 'TableOperations',{width:440}) 
     616    this.dialogRowCell.getElementById('cancel').onclick = function() { self.dialogRowCell.hide()}; 
     617  } 
     618   
     619  var dialog = this.dialogRowCell; 
     620  dialog.getElementById('title').innerHTML = cell ? Xinha._lc("Cell Properties", "TableOperations") : Xinha._lc("Row Properties", "TableOperations"); 
    622621  var Styler = new Xinha.InlineStyler(element, self.editor); 
    623          
    624         function apply() { 
    625                 var params = dialog.hide(); 
    626                 Styler.applyStyle(); 
    627                  
    628                 // various workarounds to refresh the table display (Gecko, 
    629                 // what's going on?! do not disappoint me!) 
    630                 self.editor.forceRedraw(); 
    631                 self.editor.focusEditor(); 
    632                 self.editor.updateToolbar(); 
    633                 var save_collapse = table.style.borderCollapse; 
    634                 table.style.borderCollapse = "collapse"; 
    635                 table.style.borderCollapse = "separate"; 
    636                 table.style.borderCollapse = save_collapse; 
    637         } 
    638          
    639         var st_layout = Styler.createStyleLayoutFieldset(); 
    640         var p = dialog.getElementById("TO_layout"); 
    641  
    642         p.replaceChild(st_layout,p.firstChild); 
    643          
    644         var st_prop = Styler.createStyleFieldset(); 
    645         p = dialog.getElementById("TO_style"); 
    646         p.replaceChild(st_prop,p.firstChild); 
    647  
    648         this.dialogRowCell.getElementById('ok').onclick = apply; 
    649         this.dialogRowCell.show(); 
     622   
     623  function apply() { 
     624    var params = dialog.hide(); 
     625    Styler.applyStyle(); 
     626     
     627    // various workarounds to refresh the table display (Gecko, 
     628    // what's going on?! do not disappoint me!) 
     629    self.editor.forceRedraw(); 
     630    self.editor.focusEditor(); 
     631    self.editor.updateToolbar(); 
     632    var save_collapse = table.style.borderCollapse; 
     633    table.style.borderCollapse = "collapse"; 
     634    table.style.borderCollapse = "separate"; 
     635    table.style.borderCollapse = save_collapse; 
     636  } 
     637   
     638  var st_layout = Styler.createStyleLayoutFieldset(); 
     639  var p = dialog.getElementById("TO_layout"); 
     640 
     641  p.replaceChild(st_layout,p.firstChild); 
     642   
     643  var st_prop = Styler.createStyleFieldset(); 
     644  p = dialog.getElementById("TO_style"); 
     645  p.replaceChild(st_prop,p.firstChild); 
     646 
     647  this.dialogRowCell.getElementById('ok').onclick = apply; 
     648  this.dialogRowCell.show(); 
    650649}; 
Note: See TracChangeset for help on using the changeset viewer.