File:  [LON-CAPA] / loncom / html / htmlarea / plugins / TableOperations / Attic / table-operations.js
Revision 1.2: download - view: text, annotated - select for diffs
Wed Jun 9 14:04:38 2004 UTC (20 years, 1 month ago) by www
Branches: MAIN
CVS tags: version_2_5_X, version_2_5_99_0, version_2_5_2, version_2_5_1, version_2_5_0, version_2_4_X, version_2_4_99_0, version_2_4_2, version_2_4_1, version_2_4_0, version_2_3_X, version_2_3_99_0, version_2_3_2, version_2_3_1, version_2_3_0, version_2_2_X, version_2_2_99_1, version_2_2_99_0, version_2_2_2, version_2_2_1, version_2_2_0, version_2_1_X, version_2_1_99_3, version_2_1_99_2, version_2_1_99_1, version_2_1_99_0, version_2_1_3, version_2_1_2, version_2_1_1, version_2_1_0, version_2_0_X, version_2_0_99_1, version_2_0_2, version_2_0_1, version_2_0_0, version_1_99_3, version_1_99_2, version_1_99_1_tmcc, version_1_99_1, version_1_99_0_tmcc, version_1_99_0, version_1_3_X, version_1_3_3, version_1_3_2, version_1_3_1, version_1_3_0, version_1_2_X, version_1_2_99_1, version_1_2_99_0, version_1_2_1, version_1_2_0, version_1_1_99_5, version_1_1_99_4, version_1_1_99_3, version_1_1_99_2, version_1_1_99_1, HEAD
Plugins to go with HTMLarea RC 1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>