Annotation of loncom/html/htmlarea/plugins/TableOperations/table-operations.js, revision 1.1
1.1 ! www 1: // Table Operations Plugin for HTMLArea-3.0
! 2: // Implementation by Mihai Bazon. Sponsored by http://www.bloki.com
! 3: //
! 4: // htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
! 5: // This notice MUST stay intact for use (see license.txt).
! 6: //
! 7: // A free WYSIWYG editor replacement for <textarea> fields.
! 8: // For full source code and docs, visit http://www.interactivetools.com/
! 9: //
! 10: // Version 3.0 developed by Mihai Bazon for InteractiveTools.
! 11: // http://students.infoiasi.ro/~mishoo
! 12: //
! 13: // $Id: table-operations.js,v 1.2 2003/08/10 15:56:35 mishoo Exp $
! 14:
! 15: // Object that will encapsulate all the table operations provided by
! 16: // HTMLArea-3.0 (except "insert table" which is included in the main file)
! 17: function TableOperations(editor) {
! 18: this.editor = editor;
! 19:
! 20: var cfg = editor.config;
! 21: var tt = TableOperations.I18N;
! 22: var bl = TableOperations.btnList;
! 23: var self = this;
! 24:
! 25: // register the toolbar buttons provided by this plugin
! 26: var toolbar = ["linebreak"];
! 27: for (var i in bl) {
! 28: var btn = bl[i];
! 29: if (!btn) {
! 30: toolbar.push("separator");
! 31: } else {
! 32: var id = "TO-" + btn[0];
! 33: cfg.registerButton(id, tt[id], "plugins/TableOperations/img/" + btn[0] + ".gif", false,
! 34: function(editor, id) {
! 35: // dispatch button press event
! 36: self.buttonPress(editor, id);
! 37: }, btn[1]);
! 38: toolbar.push(id);
! 39: }
! 40: }
! 41:
! 42: // add a new line in the toolbar
! 43: cfg.toolbar.push(toolbar);
! 44: };
! 45:
! 46: /************************
! 47: * UTILITIES
! 48: ************************/
! 49:
! 50: // retrieves the closest element having the specified tagName in the list of
! 51: // ancestors of the current selection/caret.
! 52: TableOperations.prototype.getClosest = function(tagName) {
! 53: var editor = this.editor;
! 54: var ancestors = editor.getAllAncestors();
! 55: var ret = null;
! 56: tagName = ("" + tagName).toLowerCase();
! 57: for (var i in ancestors) {
! 58: var el = ancestors[i];
! 59: if (el.tagName.toLowerCase() == tagName) {
! 60: ret = el;
! 61: break;
! 62: }
! 63: }
! 64: return ret;
! 65: };
! 66:
! 67: // this function requires the file PopupDiv/PopupWin to be loaded from browser
! 68: TableOperations.prototype.dialogTableProperties = function() {
! 69: var i18n = TableOperations.I18N;
! 70: // retrieve existing values
! 71: var table = this.getClosest("table");
! 72: // this.editor.selectNodeContents(table);
! 73: // this.editor.updateToolbar();
! 74:
! 75: var dialog = new PopupWin(this.editor, i18n["Table Properties"], function(dialog, params) {
! 76: TableOperations.processStyle(params, table);
! 77: for (var i in params) {
! 78: var val = params[i];
! 79: switch (i) {
! 80: case "f_caption":
! 81: if (/\S/.test(val)) {
! 82: // contains non white-space characters
! 83: var caption = table.getElementsByTagName("caption")[0];
! 84: if (!caption) {
! 85: caption = dialog.editor._doc.createElement("caption");
! 86: table.insertBefore(caption, table.firstChild);
! 87: }
! 88: caption.innerHTML = val;
! 89: } else {
! 90: // search for caption and delete it if found
! 91: var caption = table.getElementsByTagName("caption")[0];
! 92: if (caption) {
! 93: caption.parentNode.removeChild(caption);
! 94: }
! 95: }
! 96: break;
! 97: case "f_summary":
! 98: table.summary = val;
! 99: break;
! 100: case "f_width":
! 101: table.style.width = ("" + val) + params.f_unit;
! 102: break;
! 103: case "f_align":
! 104: table.align = val;
! 105: break;
! 106: case "f_spacing":
! 107: table.cellSpacing = val;
! 108: break;
! 109: case "f_padding":
! 110: table.cellPadding = val;
! 111: break;
! 112: case "f_borders":
! 113: table.border = val;
! 114: break;
! 115: case "f_frames":
! 116: table.frame = val;
! 117: break;
! 118: case "f_rules":
! 119: table.rules = val;
! 120: break;
! 121: }
! 122: }
! 123: // various workarounds to refresh the table display (Gecko,
! 124: // what's going on?! do not disappoint me!)
! 125: dialog.editor.forceRedraw();
! 126: dialog.editor.focusEditor();
! 127: dialog.editor.updateToolbar();
! 128: var save_collapse = table.style.borderCollapse;
! 129: table.style.borderCollapse = "collapse";
! 130: table.style.borderCollapse = "separate";
! 131: table.style.borderCollapse = save_collapse;
! 132: },
! 133:
! 134: // this function gets called when the dialog needs to be initialized
! 135: function (dialog) {
! 136:
! 137: var f_caption = "";
! 138: var capel = table.getElementsByTagName("caption")[0];
! 139: if (capel) {
! 140: f_caption = capel.innerHTML;
! 141: }
! 142: var f_summary = table.summary;
! 143: var f_width = parseInt(table.style.width);
! 144: isNaN(f_width) && (f_width = "");
! 145: var f_unit = /%/.test(table.style.width) ? 'percent' : 'pixels';
! 146: var f_align = table.align;
! 147: var f_spacing = table.cellSpacing;
! 148: var f_padding = table.cellPadding;
! 149: var f_borders = table.border;
! 150: var f_frames = table.frame;
! 151: var f_rules = table.rules;
! 152:
! 153: function selected(val) {
! 154: return val ? " selected" : "";
! 155: };
! 156:
! 157: // dialog contents
! 158: dialog.content.style.width = "400px";
! 159: dialog.content.innerHTML = " \
! 160: <div class='title'\
! 161: style='background: url(" + dialog.baseURL + dialog.editor.imgURL("table-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n["Table Properties"] + "\
! 162: </div> \
! 163: <table style='width:100%'> \
! 164: <tr> \
! 165: <td> \
! 166: <fieldset><legend>" + i18n["Description"] + "</legend> \
! 167: <table style='width:100%'> \
! 168: <tr> \
! 169: <td class='label'>" + i18n["Caption"] + ":</td> \
! 170: <td class='value'><input type='text' name='f_caption' value='" + f_caption + "'/></td> \
! 171: </tr><tr> \
! 172: <td class='label'>" + i18n["Summary"] + ":</td> \
! 173: <td class='value'><input type='text' name='f_summary' value='" + f_summary + "'/></td> \
! 174: </tr> \
! 175: </table> \
! 176: </fieldset> \
! 177: </td> \
! 178: </tr> \
! 179: <tr><td id='--HA-layout'></td></tr> \
! 180: <tr> \
! 181: <td> \
! 182: <fieldset><legend>" + i18n["Spacing and padding"] + "</legend> \
! 183: <table style='width:100%'> \
! 184: "+// <tr> \
! 185: // <td class='label'>" + i18n["Width"] + ":</td> \
! 186: // <td><input type='text' name='f_width' value='" + f_width + "' size='5' /> \
! 187: // <select name='f_unit'> \
! 188: // <option value='%'" + selected(f_unit == "percent") + ">" + i18n["percent"] + "</option> \
! 189: // <option value='px'" + selected(f_unit == "pixels") + ">" + i18n["pixels"] + "</option> \
! 190: // </select> " + i18n["Align"] + ": \
! 191: // <select name='f_align'> \
! 192: // <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
! 193: // <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
! 194: // <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
! 195: // </select> \
! 196: // </td> \
! 197: // </tr> \
! 198: " <tr> \
! 199: <td class='label'>" + i18n["Spacing"] + ":</td> \
! 200: <td><input type='text' name='f_spacing' size='5' value='" + f_spacing + "' /> " + i18n["Padding"] + ":\
! 201: <input type='text' name='f_padding' size='5' value='" + f_padding + "' /> " + i18n["pixels"] + "\
! 202: </td> \
! 203: </tr> \
! 204: </table> \
! 205: </fieldset> \
! 206: </td> \
! 207: </tr> \
! 208: <tr> \
! 209: <td> \
! 210: <fieldset><legend>Frame and borders</legend> \
! 211: <table width='100%'> \
! 212: <tr> \
! 213: <td class='label'>" + i18n["Borders"] + ":</td> \
! 214: <td><input name='f_borders' type='text' size='5' value='" + f_borders + "' /> " + i18n["pixels"] + "</td> \
! 215: </tr> \
! 216: <tr> \
! 217: <td class='label'>" + i18n["Frames"] + ":</td> \
! 218: <td> \
! 219: <select name='f_frames'> \
! 220: <option value='void'" + selected(f_frames == "void") + ">" + i18n["No sides"] + "</option> \
! 221: <option value='above'" + selected(f_frames == "above") + ">" + i18n["The top side only"] + "</option> \
! 222: <option value='below'" + selected(f_frames == "below") + ">" + i18n["The bottom side only"] + "</option> \
! 223: <option value='hsides'" + selected(f_frames == "hsides") + ">" + i18n["The top and bottom sides only"] + "</option> \
! 224: <option value='vsides'" + selected(f_frames == "vsides") + ">" + i18n["The right and left sides only"] + "</option> \
! 225: <option value='lhs'" + selected(f_frames == "lhs") + ">" + i18n["The left-hand side only"] + "</option> \
! 226: <option value='rhs'" + selected(f_frames == "rhs") + ">" + i18n["The right-hand side only"] + "</option> \
! 227: <option value='box'" + selected(f_frames == "box") + ">" + i18n["All four sides"] + "</option> \
! 228: </select> \
! 229: </td> \
! 230: </tr> \
! 231: <tr> \
! 232: <td class='label'>" + i18n["Rules"] + ":</td> \
! 233: <td> \
! 234: <select name='f_rules'> \
! 235: <option value='none'" + selected(f_rules == "none") + ">" + i18n["No rules"] + "</option> \
! 236: <option value='rows'" + selected(f_rules == "rows") + ">" + i18n["Rules will appear between rows only"] + "</option> \
! 237: <option value='cols'" + selected(f_rules == "cols") + ">" + i18n["Rules will appear between columns only"] + "</option> \
! 238: <option value='all'" + selected(f_rules == "all") + ">" + i18n["Rules will appear between all rows and columns"] + "</option> \
! 239: </select> \
! 240: </td> \
! 241: </tr> \
! 242: </table> \
! 243: </fieldset> \
! 244: </td> \
! 245: </tr> \
! 246: <tr> \
! 247: <td id='--HA-style'></td> \
! 248: </tr> \
! 249: </table> \
! 250: ";
! 251: var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, table);
! 252: var p = dialog.doc.getElementById("--HA-style");
! 253: p.appendChild(st_prop);
! 254: var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, table);
! 255: p = dialog.doc.getElementById("--HA-layout");
! 256: p.appendChild(st_layout);
! 257: dialog.modal = true;
! 258: dialog.addButtons("ok", "cancel");
! 259: dialog.showAtElement(dialog.editor._iframe, "c");
! 260: });
! 261: };
! 262:
! 263: // this function requires the file PopupDiv/PopupWin to be loaded from browser
! 264: TableOperations.prototype.dialogRowCellProperties = function(cell) {
! 265: var i18n = TableOperations.I18N;
! 266: // retrieve existing values
! 267: var element = this.getClosest(cell ? "td" : "tr");
! 268: var table = this.getClosest("table");
! 269: // this.editor.selectNodeContents(element);
! 270: // this.editor.updateToolbar();
! 271:
! 272: var dialog = new PopupWin(this.editor, i18n[cell ? "Cell Properties" : "Row Properties"], function(dialog, params) {
! 273: TableOperations.processStyle(params, element);
! 274: for (var i in params) {
! 275: var val = params[i];
! 276: switch (i) {
! 277: case "f_align":
! 278: element.align = val;
! 279: break;
! 280: case "f_char":
! 281: element.ch = val;
! 282: break;
! 283: case "f_valign":
! 284: element.vAlign = val;
! 285: break;
! 286: }
! 287: }
! 288: // various workarounds to refresh the table display (Gecko,
! 289: // what's going on?! do not disappoint me!)
! 290: dialog.editor.forceRedraw();
! 291: dialog.editor.focusEditor();
! 292: dialog.editor.updateToolbar();
! 293: var save_collapse = table.style.borderCollapse;
! 294: table.style.borderCollapse = "collapse";
! 295: table.style.borderCollapse = "separate";
! 296: table.style.borderCollapse = save_collapse;
! 297: },
! 298:
! 299: // this function gets called when the dialog needs to be initialized
! 300: function (dialog) {
! 301:
! 302: var f_align = element.align;
! 303: var f_valign = element.vAlign;
! 304: var f_char = element.ch;
! 305:
! 306: function selected(val) {
! 307: return val ? " selected" : "";
! 308: };
! 309:
! 310: // dialog contents
! 311: dialog.content.style.width = "400px";
! 312: dialog.content.innerHTML = " \
! 313: <div class='title'\
! 314: style='background: url(" + dialog.baseURL + dialog.editor.imgURL(cell ? "cell-prop.gif" : "row-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n[cell ? "Cell Properties" : "Row Properties"] + "</div> \
! 315: <table style='width:100%'> \
! 316: <tr> \
! 317: <td id='--HA-layout'> \
! 318: "+// <fieldset><legend>" + i18n["Layout"] + "</legend> \
! 319: // <table style='width:100%'> \
! 320: // <tr> \
! 321: // <td class='label'>" + i18n["Align"] + ":</td> \
! 322: // <td> \
! 323: // <select name='f_align'> \
! 324: // <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
! 325: // <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
! 326: // <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
! 327: // <option value='char'" + selected(f_align == "char") + ">" + i18n["Char"] + "</option> \
! 328: // </select> \
! 329: // " + i18n["Char"] + ": \
! 330: // <input type='text' style='font-family: monospace; text-align: center' name='f_char' size='1' value='" + f_char + "' /> \
! 331: // </td> \
! 332: // </tr><tr> \
! 333: // <td class='label'>" + i18n["Vertical align"] + ":</td> \
! 334: // <td> \
! 335: // <select name='f_valign'> \
! 336: // <option value='top'" + selected(f_valign == "top") + ">" + i18n["Top"] + "</option> \
! 337: // <option value='middle'" + selected(f_valign == "middle") + ">" + i18n["Middle"] + "</option> \
! 338: // <option value='bottom'" + selected(f_valign == "bottom") + ">" + i18n["Bottom"] + "</option> \
! 339: // <option value='baseline'" + selected(f_valign == "baseline") + ">" + i18n["Baseline"] + "</option> \
! 340: // </select> \
! 341: // </td> \
! 342: // </tr> \
! 343: // </table> \
! 344: // </fieldset> \
! 345: " </td> \
! 346: </tr> \
! 347: <tr> \
! 348: <td id='--HA-style'></td> \
! 349: </tr> \
! 350: </table> \
! 351: ";
! 352: var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, element);
! 353: var p = dialog.doc.getElementById("--HA-style");
! 354: p.appendChild(st_prop);
! 355: var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, element);
! 356: p = dialog.doc.getElementById("--HA-layout");
! 357: p.appendChild(st_layout);
! 358: dialog.modal = true;
! 359: dialog.addButtons("ok", "cancel");
! 360: dialog.showAtElement(dialog.editor._iframe, "c");
! 361: });
! 362: };
! 363:
! 364: // this function gets called when some button from the TableOperations toolbar
! 365: // was pressed.
! 366: TableOperations.prototype.buttonPress = function(editor, button_id) {
! 367: this.editor = editor;
! 368: var mozbr = HTMLArea.is_gecko ? "<br />" : "";
! 369: var i18n = TableOperations.I18N;
! 370:
! 371: // helper function that clears the content in a table row
! 372: function clearRow(tr) {
! 373: var tds = tr.getElementsByTagName("td");
! 374: for (var i = tds.length; --i >= 0;) {
! 375: var td = tds[i];
! 376: td.rowSpan = 1;
! 377: td.innerHTML = mozbr;
! 378: }
! 379: };
! 380:
! 381: function splitRow(td) {
! 382: var n = parseInt("" + td.rowSpan);
! 383: var nc = parseInt("" + td.colSpan);
! 384: td.rowSpan = 1;
! 385: tr = td.parentNode;
! 386: var itr = tr.rowIndex;
! 387: var trs = tr.parentNode.rows;
! 388: var index = td.cellIndex;
! 389: while (--n > 0) {
! 390: tr = trs[++itr];
! 391: var otd = editor._doc.createElement("td");
! 392: otd.colSpan = td.colSpan;
! 393: otd.innerHTML = mozbr;
! 394: tr.insertBefore(otd, tr.cells[index]);
! 395: }
! 396: editor.forceRedraw();
! 397: editor.updateToolbar();
! 398: };
! 399:
! 400: function splitCol(td) {
! 401: var nc = parseInt("" + td.colSpan);
! 402: td.colSpan = 1;
! 403: tr = td.parentNode;
! 404: var ref = td.nextSibling;
! 405: while (--nc > 0) {
! 406: var otd = editor._doc.createElement("td");
! 407: otd.rowSpan = td.rowSpan;
! 408: otd.innerHTML = mozbr;
! 409: tr.insertBefore(otd, ref);
! 410: }
! 411: editor.forceRedraw();
! 412: editor.updateToolbar();
! 413: };
! 414:
! 415: function splitCell(td) {
! 416: var nc = parseInt("" + td.colSpan);
! 417: splitCol(td);
! 418: var items = td.parentNode.cells;
! 419: var index = td.cellIndex;
! 420: while (nc-- > 0) {
! 421: splitRow(items[index++]);
! 422: }
! 423: };
! 424:
! 425: function selectNextNode(el) {
! 426: var node = el.nextSibling;
! 427: while (node && node.nodeType != 1) {
! 428: node = node.nextSibling;
! 429: }
! 430: if (!node) {
! 431: node = el.previousSibling;
! 432: while (node && node.nodeType != 1) {
! 433: node = node.previousSibling;
! 434: }
! 435: }
! 436: if (!node) {
! 437: node = el.parentNode;
! 438: }
! 439: editor.selectNodeContents(node);
! 440: };
! 441:
! 442: switch (button_id) {
! 443: // ROWS
! 444:
! 445: case "TO-row-insert-above":
! 446: case "TO-row-insert-under":
! 447: var tr = this.getClosest("tr");
! 448: if (!tr) {
! 449: break;
! 450: }
! 451: var otr = tr.cloneNode(true);
! 452: clearRow(otr);
! 453: tr.parentNode.insertBefore(otr, /under/.test(button_id) ? tr.nextSibling : tr);
! 454: editor.forceRedraw();
! 455: editor.focusEditor();
! 456: break;
! 457: case "TO-row-delete":
! 458: var tr = this.getClosest("tr");
! 459: if (!tr) {
! 460: break;
! 461: }
! 462: var par = tr.parentNode;
! 463: if (par.rows.length == 1) {
! 464: alert(i18n["not-del-last-row"]);
! 465: break;
! 466: }
! 467: // set the caret first to a position that doesn't
! 468: // disappear.
! 469: selectNextNode(tr);
! 470: par.removeChild(tr);
! 471: editor.forceRedraw();
! 472: editor.focusEditor();
! 473: editor.updateToolbar();
! 474: break;
! 475: case "TO-row-split":
! 476: var td = this.getClosest("td");
! 477: if (!td) {
! 478: break;
! 479: }
! 480: splitRow(td);
! 481: break;
! 482:
! 483: // COLUMNS
! 484:
! 485: case "TO-col-insert-before":
! 486: case "TO-col-insert-after":
! 487: var td = this.getClosest("td");
! 488: if (!td) {
! 489: break;
! 490: }
! 491: var rows = td.parentNode.parentNode.rows;
! 492: var index = td.cellIndex;
! 493: for (var i = rows.length; --i >= 0;) {
! 494: var tr = rows[i];
! 495: var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)];
! 496: var otd = editor._doc.createElement("td");
! 497: otd.innerHTML = mozbr;
! 498: tr.insertBefore(otd, ref);
! 499: }
! 500: editor.focusEditor();
! 501: break;
! 502: case "TO-col-split":
! 503: var td = this.getClosest("td");
! 504: if (!td) {
! 505: break;
! 506: }
! 507: splitCol(td);
! 508: break;
! 509: case "TO-col-delete":
! 510: var td = this.getClosest("td");
! 511: if (!td) {
! 512: break;
! 513: }
! 514: var index = td.cellIndex;
! 515: if (td.parentNode.cells.length == 1) {
! 516: alert(i18n["not-del-last-col"]);
! 517: break;
! 518: }
! 519: // set the caret first to a position that doesn't disappear
! 520: selectNextNode(td);
! 521: var rows = td.parentNode.parentNode.rows;
! 522: for (var i = rows.length; --i >= 0;) {
! 523: var tr = rows[i];
! 524: tr.removeChild(tr.cells[index]);
! 525: }
! 526: editor.forceRedraw();
! 527: editor.focusEditor();
! 528: editor.updateToolbar();
! 529: break;
! 530:
! 531: // CELLS
! 532:
! 533: case "TO-cell-split":
! 534: var td = this.getClosest("td");
! 535: if (!td) {
! 536: break;
! 537: }
! 538: splitCell(td);
! 539: break;
! 540: case "TO-cell-insert-before":
! 541: case "TO-cell-insert-after":
! 542: var td = this.getClosest("td");
! 543: if (!td) {
! 544: break;
! 545: }
! 546: var tr = td.parentNode;
! 547: var otd = editor._doc.createElement("td");
! 548: otd.innerHTML = mozbr;
! 549: tr.insertBefore(otd, /after/.test(button_id) ? td.nextSibling : td);
! 550: editor.forceRedraw();
! 551: editor.focusEditor();
! 552: break;
! 553: case "TO-cell-delete":
! 554: var td = this.getClosest("td");
! 555: if (!td) {
! 556: break;
! 557: }
! 558: if (td.parentNode.cells.length == 1) {
! 559: alert(i18n["not-del-last-cell"]);
! 560: break;
! 561: }
! 562: // set the caret first to a position that doesn't disappear
! 563: selectNextNode(td);
! 564: td.parentNode.removeChild(td);
! 565: editor.forceRedraw();
! 566: editor.updateToolbar();
! 567: break;
! 568: case "TO-cell-merge":
! 569: // !! FIXME: Mozilla specific !!
! 570: var sel = editor._getSelection();
! 571: var range, i = 0;
! 572: var rows = [];
! 573: var row = null;
! 574: var cells = null;
! 575: if (!HTMLArea.is_ie) {
! 576: try {
! 577: while (range = sel.getRangeAt(i++)) {
! 578: var td = range.startContainer.childNodes[range.startOffset];
! 579: if (td.parentNode != row) {
! 580: row = td.parentNode;
! 581: (cells) && rows.push(cells);
! 582: cells = [];
! 583: }
! 584: cells.push(td);
! 585: }
! 586: } catch(e) {/* finished walking through selection */}
! 587: rows.push(cells);
! 588: } else {
! 589: // Internet Explorer "browser"
! 590: var td = this.getClosest("td");
! 591: if (!td) {
! 592: alert(i18n["Please click into some cell"]);
! 593: break;
! 594: }
! 595: var tr = td.parentElement;
! 596: var no_cols = prompt(i18n["How many columns would you like to merge?"], 2);
! 597: if (!no_cols) {
! 598: // cancelled
! 599: break;
! 600: }
! 601: var no_rows = prompt(i18n["How many rows would you like to merge?"], 2);
! 602: if (!no_rows) {
! 603: // cancelled
! 604: break;
! 605: }
! 606: var cell_index = td.cellIndex;
! 607: while (no_rows-- > 0) {
! 608: td = tr.cells[cell_index];
! 609: cells = [td];
! 610: for (var i = 1; i < no_cols; ++i) {
! 611: td = td.nextSibling;
! 612: if (!td) {
! 613: break;
! 614: }
! 615: cells.push(td);
! 616: }
! 617: rows.push(cells);
! 618: tr = tr.nextSibling;
! 619: if (!tr) {
! 620: break;
! 621: }
! 622: }
! 623: }
! 624: var HTML = "";
! 625: for (i = 0; i < rows.length; ++i) {
! 626: // i && (HTML += "<br />");
! 627: var cells = rows[i];
! 628: for (var j = 0; j < cells.length; ++j) {
! 629: // j && (HTML += " ");
! 630: var cell = cells[j];
! 631: HTML += cell.innerHTML;
! 632: (i || j) && (cell.parentNode.removeChild(cell));
! 633: }
! 634: }
! 635: var td = rows[0][0];
! 636: td.innerHTML = HTML;
! 637: td.rowSpan = rows.length;
! 638: td.colSpan = rows[0].length;
! 639: editor.selectNodeContents(td);
! 640: editor.forceRedraw();
! 641: editor.focusEditor();
! 642: break;
! 643:
! 644: // PROPERTIES
! 645:
! 646: case "TO-table-prop":
! 647: this.dialogTableProperties();
! 648: break;
! 649:
! 650: case "TO-row-prop":
! 651: this.dialogRowCellProperties(false);
! 652: break;
! 653:
! 654: case "TO-cell-prop":
! 655: this.dialogRowCellProperties(true);
! 656: break;
! 657:
! 658: default:
! 659: alert("Button [" + button_id + "] not yet implemented");
! 660: }
! 661: };
! 662:
! 663: // the list of buttons added by this plugin
! 664: TableOperations.btnList = [
! 665: // table properties button
! 666: ["table-prop", "table"],
! 667: null, // separator
! 668:
! 669: // ROWS
! 670: ["row-prop", "tr"],
! 671: ["row-insert-above", "tr"],
! 672: ["row-insert-under", "tr"],
! 673: ["row-delete", "tr"],
! 674: ["row-split", "td[rowSpan!=1]"],
! 675: null,
! 676:
! 677: // COLS
! 678: ["col-insert-before", "td"],
! 679: ["col-insert-after", "td"],
! 680: ["col-delete", "td"],
! 681: ["col-split", "td[colSpan!=1]"],
! 682: null,
! 683:
! 684: // CELLS
! 685: ["cell-prop", "td"],
! 686: ["cell-insert-before", "td"],
! 687: ["cell-insert-after", "td"],
! 688: ["cell-delete", "td"],
! 689: ["cell-merge", "tr"],
! 690: ["cell-split", "td[colSpan!=1,rowSpan!=1]"]
! 691: ];
! 692:
! 693:
! 694:
! 695: //// GENERIC CODE [style of any element; this should be moved into a separate
! 696: //// file as it'll be very useful]
! 697: //// BEGIN GENERIC CODE -----------------------------------------------------
! 698:
! 699: TableOperations.getLength = function(value) {
! 700: var len = parseInt(value);
! 701: if (isNaN(len)) {
! 702: len = "";
! 703: }
! 704: return len;
! 705: };
! 706:
! 707: // Applies the style found in "params" to the given element.
! 708: TableOperations.processStyle = function(params, element) {
! 709: var style = element.style;
! 710: for (var i in params) {
! 711: var val = params[i];
! 712: switch (i) {
! 713: case "f_st_backgroundColor":
! 714: style.backgroundColor = val;
! 715: break;
! 716: case "f_st_color":
! 717: style.color = val;
! 718: break;
! 719: case "f_st_backgroundImage":
! 720: if (/\S/.test(val)) {
! 721: style.backgroundImage = "url(" + val + ")";
! 722: } else {
! 723: style.backgroundImage = "none";
! 724: }
! 725: break;
! 726: case "f_st_borderWidth":
! 727: style.borderWidth = val;
! 728: break;
! 729: case "f_st_borderStyle":
! 730: style.borderStyle = val;
! 731: break;
! 732: case "f_st_borderColor":
! 733: style.borderColor = val;
! 734: break;
! 735: case "f_st_borderCollapse":
! 736: style.borderCollapse = val ? "collapse" : "";
! 737: break;
! 738: case "f_st_width":
! 739: if (/\S/.test(val)) {
! 740: style.width = val + params["f_st_widthUnit"];
! 741: } else {
! 742: style.width = "";
! 743: }
! 744: break;
! 745: case "f_st_height":
! 746: if (/\S/.test(val)) {
! 747: style.height = val + params["f_st_heightUnit"];
! 748: } else {
! 749: style.height = "";
! 750: }
! 751: break;
! 752: case "f_st_textAlign":
! 753: if (val == "char") {
! 754: var ch = params["f_st_textAlignChar"];
! 755: if (ch == '"') {
! 756: ch = '\\"';
! 757: }
! 758: style.textAlign = '"' + ch + '"';
! 759: } else {
! 760: style.textAlign = val;
! 761: }
! 762: break;
! 763: case "f_st_verticalAlign":
! 764: style.verticalAlign = val;
! 765: break;
! 766: case "f_st_float":
! 767: style.cssFloat = val;
! 768: break;
! 769: // case "f_st_margin":
! 770: // style.margin = val + "px";
! 771: // break;
! 772: // case "f_st_padding":
! 773: // style.padding = val + "px";
! 774: // break;
! 775: }
! 776: }
! 777: };
! 778:
! 779: // Returns an HTML element for a widget that allows color selection. That is,
! 780: // a button that contains the given color, if any, and when pressed will popup
! 781: // the sooner-or-later-to-be-rewritten select_color.html dialog allowing user
! 782: // to select some color. If a color is selected, an input field with the name
! 783: // "f_st_"+name will be updated with the color value in #123456 format.
! 784: TableOperations.createColorButton = function(doc, editor, color, name) {
! 785: if (!color) {
! 786: color = "";
! 787: } else if (!/#/.test(color)) {
! 788: color = HTMLArea._colorToRgb(color);
! 789: }
! 790:
! 791: var df = doc.createElement("span");
! 792: var field = doc.createElement("input");
! 793: field.type = "hidden";
! 794: df.appendChild(field);
! 795: field.name = "f_st_" + name;
! 796: field.value = color;
! 797: var button = doc.createElement("span");
! 798: button.className = "buttonColor";
! 799: df.appendChild(button);
! 800: var span = doc.createElement("span");
! 801: span.className = "chooser";
! 802: // span.innerHTML = " ";
! 803: span.style.backgroundColor = color;
! 804: button.appendChild(span);
! 805: button.onmouseover = function() { if (!this.disabled) { this.className += " buttonColor-hilite"; }};
! 806: button.onmouseout = function() { if (!this.disabled) { this.className = "buttonColor"; }};
! 807: span.onclick = function() {
! 808: if (this.parentNode.disabled) {
! 809: return false;
! 810: }
! 811: editor._popupDialog("select_color.html", function(color) {
! 812: if (color) {
! 813: span.style.backgroundColor = "#" + color;
! 814: field.value = "#" + color;
! 815: }
! 816: }, color);
! 817: };
! 818: var span2 = doc.createElement("span");
! 819: span2.innerHTML = "×";
! 820: span2.className = "nocolor";
! 821: span2.title = TableOperations.I18N["Unset color"];
! 822: button.appendChild(span2);
! 823: span2.onmouseover = function() { if (!this.parentNode.disabled) { this.className += " nocolor-hilite"; }};
! 824: span2.onmouseout = function() { if (!this.parentNode.disabled) { this.className = "nocolor"; }};
! 825: span2.onclick = function() {
! 826: span.style.backgroundColor = "";
! 827: field.value = "";
! 828: };
! 829: return df;
! 830: };
! 831:
! 832: TableOperations.createStyleLayoutFieldset = function(doc, editor, el) {
! 833: var i18n = TableOperations.I18N;
! 834: var fieldset = doc.createElement("fieldset");
! 835: var legend = doc.createElement("legend");
! 836: fieldset.appendChild(legend);
! 837: legend.innerHTML = i18n["Layout"];
! 838: var table = doc.createElement("table");
! 839: fieldset.appendChild(table);
! 840: table.style.width = "100%";
! 841: var tbody = doc.createElement("tbody");
! 842: table.appendChild(tbody);
! 843:
! 844: var tagname = el.tagName.toLowerCase();
! 845: var tr, td, input, select, option, options, i;
! 846:
! 847: if (tagname != "td" && tagname != "tr" && tagname != "th") {
! 848: tr = doc.createElement("tr");
! 849: tbody.appendChild(tr);
! 850: td = doc.createElement("td");
! 851: td.className = "label";
! 852: tr.appendChild(td);
! 853: td.innerHTML = i18n["Float"] + ":";
! 854: td = doc.createElement("td");
! 855: tr.appendChild(td);
! 856: select = doc.createElement("select");
! 857: td.appendChild(select);
! 858: select.name = "f_st_float";
! 859: options = ["None", "Left", "Right"];
! 860: for (i in options) {
! 861: var Val = options[i];
! 862: var val = options[i].toLowerCase();
! 863: option = doc.createElement("option");
! 864: option.innerHTML = i18n[Val];
! 865: option.value = val;
! 866: option.selected = (("" + el.style.cssFloat).toLowerCase() == val);
! 867: select.appendChild(option);
! 868: }
! 869: }
! 870:
! 871: tr = doc.createElement("tr");
! 872: tbody.appendChild(tr);
! 873: td = doc.createElement("td");
! 874: td.className = "label";
! 875: tr.appendChild(td);
! 876: td.innerHTML = i18n["Width"] + ":";
! 877: td = doc.createElement("td");
! 878: tr.appendChild(td);
! 879: input = doc.createElement("input");
! 880: input.type = "text";
! 881: input.value = TableOperations.getLength(el.style.width);
! 882: input.size = "5";
! 883: input.name = "f_st_width";
! 884: input.style.marginRight = "0.5em";
! 885: td.appendChild(input);
! 886: select = doc.createElement("select");
! 887: select.name = "f_st_widthUnit";
! 888: option = doc.createElement("option");
! 889: option.innerHTML = i18n["percent"];
! 890: option.value = "%";
! 891: option.selected = /%/.test(el.style.width);
! 892: select.appendChild(option);
! 893: option = doc.createElement("option");
! 894: option.innerHTML = i18n["pixels"];
! 895: option.value = "px";
! 896: option.selected = /px/.test(el.style.width);
! 897: select.appendChild(option);
! 898: td.appendChild(select);
! 899:
! 900: select.style.marginRight = "0.5em";
! 901: td.appendChild(doc.createTextNode(i18n["Text align"] + ":"));
! 902: select = doc.createElement("select");
! 903: select.style.marginLeft = select.style.marginRight = "0.5em";
! 904: td.appendChild(select);
! 905: select.name = "f_st_textAlign";
! 906: options = ["Left", "Center", "Right", "Justify"];
! 907: if (tagname == "td") {
! 908: options.push("Char");
! 909: }
! 910: input = doc.createElement("input");
! 911: input.name = "f_st_textAlignChar";
! 912: input.size = "1";
! 913: input.style.fontFamily = "monospace";
! 914: td.appendChild(input);
! 915: for (i in options) {
! 916: var Val = options[i];
! 917: var val = Val.toLowerCase();
! 918: option = doc.createElement("option");
! 919: option.value = val;
! 920: option.innerHTML = i18n[Val];
! 921: option.selected = (el.style.textAlign.toLowerCase() == val);
! 922: select.appendChild(option);
! 923: }
! 924: function setCharVisibility(value) {
! 925: input.style.visibility = value ? "visible" : "hidden";
! 926: if (value) {
! 927: input.focus();
! 928: input.select();
! 929: }
! 930: };
! 931: select.onchange = function() { setCharVisibility(this.value == "char"); };
! 932: setCharVisibility(select.value == "char");
! 933:
! 934: tr = doc.createElement("tr");
! 935: tbody.appendChild(tr);
! 936: td = doc.createElement("td");
! 937: td.className = "label";
! 938: tr.appendChild(td);
! 939: td.innerHTML = i18n["Height"] + ":";
! 940: td = doc.createElement("td");
! 941: tr.appendChild(td);
! 942: input = doc.createElement("input");
! 943: input.type = "text";
! 944: input.value = TableOperations.getLength(el.style.height);
! 945: input.size = "5";
! 946: input.name = "f_st_height";
! 947: input.style.marginRight = "0.5em";
! 948: td.appendChild(input);
! 949: select = doc.createElement("select");
! 950: select.name = "f_st_heightUnit";
! 951: option = doc.createElement("option");
! 952: option.innerHTML = i18n["percent"];
! 953: option.value = "%";
! 954: option.selected = /%/.test(el.style.height);
! 955: select.appendChild(option);
! 956: option = doc.createElement("option");
! 957: option.innerHTML = i18n["pixels"];
! 958: option.value = "px";
! 959: option.selected = /px/.test(el.style.height);
! 960: select.appendChild(option);
! 961: td.appendChild(select);
! 962:
! 963: select.style.marginRight = "0.5em";
! 964: td.appendChild(doc.createTextNode(i18n["Vertical align"] + ":"));
! 965: select = doc.createElement("select");
! 966: select.name = "f_st_verticalAlign";
! 967: select.style.marginLeft = "0.5em";
! 968: td.appendChild(select);
! 969: options = ["Top", "Middle", "Bottom", "Baseline"];
! 970: for (i in options) {
! 971: var Val = options[i];
! 972: var val = Val.toLowerCase();
! 973: option = doc.createElement("option");
! 974: option.value = val;
! 975: option.innerHTML = i18n[Val];
! 976: option.selected = (el.style.verticalAlign.toLowerCase() == val);
! 977: select.appendChild(option);
! 978: }
! 979:
! 980: return fieldset;
! 981: };
! 982:
! 983: // Returns an HTML element containing the style attributes for the given
! 984: // element. This can be easily embedded into any dialog; the functionality is
! 985: // also provided.
! 986: TableOperations.createStyleFieldset = function(doc, editor, el) {
! 987: var i18n = TableOperations.I18N;
! 988: var fieldset = doc.createElement("fieldset");
! 989: var legend = doc.createElement("legend");
! 990: fieldset.appendChild(legend);
! 991: legend.innerHTML = i18n["CSS Style"];
! 992: var table = doc.createElement("table");
! 993: fieldset.appendChild(table);
! 994: table.style.width = "100%";
! 995: var tbody = doc.createElement("tbody");
! 996: table.appendChild(tbody);
! 997:
! 998: var tr, td, input, select, option, options, i;
! 999:
! 1000: tr = doc.createElement("tr");
! 1001: tbody.appendChild(tr);
! 1002: td = doc.createElement("td");
! 1003: tr.appendChild(td);
! 1004: td.className = "label";
! 1005: td.innerHTML = i18n["Background"] + ":";
! 1006: td = doc.createElement("td");
! 1007: tr.appendChild(td);
! 1008: var df = TableOperations.createColorButton(doc, editor, el.style.backgroundColor, "backgroundColor");
! 1009: df.firstChild.nextSibling.style.marginRight = "0.5em";
! 1010: td.appendChild(df);
! 1011: td.appendChild(doc.createTextNode(i18n["Image URL"] + ": "));
! 1012: input = doc.createElement("input");
! 1013: input.type = "text";
! 1014: input.name = "f_st_backgroundImage";
! 1015: if (el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) {
! 1016: input.value = RegExp.$1;
! 1017: }
! 1018: // input.style.width = "100%";
! 1019: td.appendChild(input);
! 1020:
! 1021: tr = doc.createElement("tr");
! 1022: tbody.appendChild(tr);
! 1023: td = doc.createElement("td");
! 1024: tr.appendChild(td);
! 1025: td.className = "label";
! 1026: td.innerHTML = i18n["FG Color"] + ":";
! 1027: td = doc.createElement("td");
! 1028: tr.appendChild(td);
! 1029: td.appendChild(TableOperations.createColorButton(doc, editor, el.style.color, "color"));
! 1030:
! 1031: // for better alignment we include an invisible field.
! 1032: input = doc.createElement("input");
! 1033: input.style.visibility = "hidden";
! 1034: input.type = "text";
! 1035: td.appendChild(input);
! 1036:
! 1037: tr = doc.createElement("tr");
! 1038: tbody.appendChild(tr);
! 1039: td = doc.createElement("td");
! 1040: tr.appendChild(td);
! 1041: td.className = "label";
! 1042: td.innerHTML = i18n["Border"] + ":";
! 1043: td = doc.createElement("td");
! 1044: tr.appendChild(td);
! 1045:
! 1046: var colorButton = TableOperations.createColorButton(doc, editor, el.style.borderColor, "borderColor");
! 1047: var btn = colorButton.firstChild.nextSibling;
! 1048: td.appendChild(colorButton);
! 1049: // borderFields.push(btn);
! 1050: btn.style.marginRight = "0.5em";
! 1051:
! 1052: select = doc.createElement("select");
! 1053: var borderFields = [];
! 1054: td.appendChild(select);
! 1055: select.name = "f_st_borderStyle";
! 1056: options = ["none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"];
! 1057: var currentBorderStyle = el.style.borderStyle;
! 1058: // Gecko reports "solid solid solid solid" for "border-style: solid".
! 1059: // That is, "top right bottom left" -- we only consider the first
! 1060: // value.
! 1061: (currentBorderStyle.match(/([^\s]*)\s/)) && (currentBorderStyle = RegExp.$1);
! 1062: for (i in options) {
! 1063: var val = options[i];
! 1064: option = doc.createElement("option");
! 1065: option.value = val;
! 1066: option.innerHTML = val;
! 1067: (val == currentBorderStyle) && (option.selected = true);
! 1068: select.appendChild(option);
! 1069: }
! 1070: select.style.marginRight = "0.5em";
! 1071: function setBorderFieldsStatus(value) {
! 1072: for (i in borderFields) {
! 1073: var el = borderFields[i];
! 1074: el.style.visibility = value ? "hidden" : "visible";
! 1075: if (!value && (el.tagName.toLowerCase() == "input")) {
! 1076: el.focus();
! 1077: el.select();
! 1078: }
! 1079: }
! 1080: };
! 1081: select.onchange = function() { setBorderFieldsStatus(this.value == "none"); };
! 1082:
! 1083: input = doc.createElement("input");
! 1084: borderFields.push(input);
! 1085: input.type = "text";
! 1086: input.name = "f_st_borderWidth";
! 1087: input.value = TableOperations.getLength(el.style.borderWidth);
! 1088: input.size = "5";
! 1089: td.appendChild(input);
! 1090: input.style.marginRight = "0.5em";
! 1091: var span = doc.createElement("span");
! 1092: span.innerHTML = i18n["pixels"];
! 1093: td.appendChild(span);
! 1094: borderFields.push(span);
! 1095:
! 1096: setBorderFieldsStatus(select.value == "none");
! 1097:
! 1098: if (el.tagName.toLowerCase() == "table") {
! 1099: // the border-collapse style is only for tables
! 1100: tr = doc.createElement("tr");
! 1101: tbody.appendChild(tr);
! 1102: td = doc.createElement("td");
! 1103: td.className = "label";
! 1104: tr.appendChild(td);
! 1105: input = doc.createElement("input");
! 1106: input.type = "checkbox";
! 1107: input.name = "f_st_borderCollapse";
! 1108: input.id = "f_st_borderCollapse";
! 1109: var val = (/collapse/i.test(el.style.borderCollapse));
! 1110: input.checked = val ? 1 : 0;
! 1111: td.appendChild(input);
! 1112:
! 1113: td = doc.createElement("td");
! 1114: tr.appendChild(td);
! 1115: var label = doc.createElement("label");
! 1116: label.htmlFor = "f_st_borderCollapse";
! 1117: label.innerHTML = i18n["Collapsed borders"];
! 1118: td.appendChild(label);
! 1119: }
! 1120:
! 1121: // tr = doc.createElement("tr");
! 1122: // tbody.appendChild(tr);
! 1123: // td = doc.createElement("td");
! 1124: // td.className = "label";
! 1125: // tr.appendChild(td);
! 1126: // td.innerHTML = i18n["Margin"] + ":";
! 1127: // td = doc.createElement("td");
! 1128: // tr.appendChild(td);
! 1129: // input = doc.createElement("input");
! 1130: // input.type = "text";
! 1131: // input.size = "5";
! 1132: // input.name = "f_st_margin";
! 1133: // td.appendChild(input);
! 1134: // input.style.marginRight = "0.5em";
! 1135: // td.appendChild(doc.createTextNode(i18n["Padding"] + ":"));
! 1136:
! 1137: // input = doc.createElement("input");
! 1138: // input.type = "text";
! 1139: // input.size = "5";
! 1140: // input.name = "f_st_padding";
! 1141: // td.appendChild(input);
! 1142: // input.style.marginLeft = "0.5em";
! 1143: // input.style.marginRight = "0.5em";
! 1144: // td.appendChild(doc.createTextNode(i18n["pixels"]));
! 1145:
! 1146: return fieldset;
! 1147: };
! 1148:
! 1149: //// END GENERIC CODE -------------------------------------------------------
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>