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