!import
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is Mozilla Communicator client code, released
15 * March 31, 1998.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-1999
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 * Ben Goodger
24 * Charles Manske (cmanske@netscape.com)
25 * Neil Rashbrook (neil@parkwaycc.co.uk)
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
38 *
39 * ***** END LICENSE BLOCK ***** */
40
41 //Cancel() is in EdDialogCommon.js
42 var gTableElement;
43 var gCellElement;
44 var gTableCaptionElement;
45 var globalCellElement;
46 var globalTableElement
47 var gValidateTab;
48 const defHAlign = "left";
49 const centerStr = "center"; //Index=1
50 const rightStr = "right"; // 2
51 const justifyStr = "justify"; // 3
52 const charStr = "char"; // 4
53 const defVAlign = "middle";
54 const topStr = "top";
55 const bottomStr = "bottom";
56 const bgcolor = "bgcolor";
57 var gTableColor;
58 var gCellColor;
59
60 const cssBackgroundColorStr = "background-color";
61
62 var gRowCount = 1;
63 var gColCount = 1;
64 var gLastRowIndex;
65 var gLastColIndex;
66 var gNewRowCount;
67 var gNewColCount;
68 var gCurRowIndex;
69 var gCurColIndex;
70 var gCurColSpan;
71 var gSelectedCellsType = 1;
72 const SELECT_CELL = 1;
73 const SELECT_ROW = 2;
74 const SELECT_COLUMN = 3;
75 const RESET_SELECTION = 0;
76 var gCellData = { value:null, startRowIndex:0, startColIndex:0, rowSpan:0, colSpan:0,
77 actualRowSpan:0, actualColSpan:0, isSelected:false
78 };
79 var gAdvancedEditUsed;
80 var gAlignWasChar = false;
81
82 /*
83 From C++:
84 0 TABLESELECTION_TABLE
85 1 TABLESELECTION_CELL There are 1 or more cells selected
86 but complete rows or columns are not selected
87 2 TABLESELECTION_ROW All cells are in 1 or more rows
88 and in each row, all cells selected
89 Note: This is the value if all rows (thus all cells) are selected
90 3 TABLESELECTION_COLUMN All cells are in 1 or more columns
91 */
92
93 var gSelectedCellCount = 0;
94 var gApplyUsed = false;
95 var gSelection;
96 var gCellDataChanged = false;
97 var gCanDelete = false;
98 var gPrefs = GetPrefs();
99 var gUseCSS = true;
100 var gActiveEditor;
101
102 // dialog initialization code
Startup
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
103 function Startup()
104 {
105 gActiveEditor = GetCurrentTableEditor();
106 if (!gActiveEditor)
107 {
108 window.close();
109 return;
110 }
111
112 try {
113 gSelection = gActiveEditor.selection;
114 } catch (e) {}
115 if (!gSelection) return;
116
117 // Get dialog widgets - Table Panel
118 gDialog.TableRowsInput = document.getElementById("TableRowsInput");
119 gDialog.TableColumnsInput = document.getElementById("TableColumnsInput");
120 gDialog.TableWidthInput = document.getElementById("TableWidthInput");
121 gDialog.TableWidthUnits = document.getElementById("TableWidthUnits");
122 gDialog.TableHeightInput = document.getElementById("TableHeightInput");
123 gDialog.TableHeightUnits = document.getElementById("TableHeightUnits");
124 try {
125 if (!gPrefs.getBoolPref("editor.use_css") || (gActiveEditor.flags & 1))
126 {
127 gUseCSS = false;
128 var tableHeightLabel = document.getElementById("TableHeightLabel");
129 tableHeightLabel.parentNode.removeChild(tableHeightLabel);
130 gDialog.TableHeightInput.parentNode.removeChild(gDialog.TableHeightInput);
131 gDialog.TableHeightUnits.parentNode.removeChild(gDialog.TableHeightUnits);
132 }
133 } catch (e) {}
134 gDialog.BorderWidthInput = document.getElementById("BorderWidthInput");
135 gDialog.SpacingInput = document.getElementById("SpacingInput");
136 gDialog.PaddingInput = document.getElementById("PaddingInput");
137 gDialog.TableAlignList = document.getElementById("TableAlignList");
138 gDialog.TableCaptionList = document.getElementById("TableCaptionList");
139 gDialog.TableInheritColor = document.getElementById("TableInheritColor");
140 gDialog.TabBox = document.getElementById("TabBox");
141
142 // Cell Panel
143 gDialog.SelectionList = document.getElementById("SelectionList");
144 gDialog.PreviousButton = document.getElementById("PreviousButton");
145 gDialog.NextButton = document.getElementById("NextButton");
146 // Currently, we always apply changes and load new attributes when changing selection
147 // (Let's keep this for possible future use)
148 //gDialog.ApplyBeforeMove = document.getElementById("ApplyBeforeMove");
149 //gDialog.KeepCurrentData = document.getElementById("KeepCurrentData");
150
151 gDialog.CellHeightInput = document.getElementById("CellHeightInput");
152 gDialog.CellHeightUnits = document.getElementById("CellHeightUnits");
153 gDialog.CellWidthInput = document.getElementById("CellWidthInput");
154 gDialog.CellWidthUnits = document.getElementById("CellWidthUnits");
155 gDialog.CellHAlignList = document.getElementById("CellHAlignList");
156 gDialog.CellVAlignList = document.getElementById("CellVAlignList");
157 gDialog.CellInheritColor = document.getElementById("CellInheritColor");
158 gDialog.CellStyleList = document.getElementById("CellStyleList");
159 gDialog.TextWrapList = document.getElementById("TextWrapList");
160
161 // In cell panel, user must tell us which attributes to apply via checkboxes,
162 // else we would apply values from one cell to ALL in selection
163 // and that's probably not what they expect!
164 gDialog.CellHeightCheckbox = document.getElementById("CellHeightCheckbox");
165 gDialog.CellWidthCheckbox = document.getElementById("CellWidthCheckbox");
166 gDialog.CellHAlignCheckbox = document.getElementById("CellHAlignCheckbox");
167 gDialog.CellVAlignCheckbox = document.getElementById("CellVAlignCheckbox");
168 gDialog.CellStyleCheckbox = document.getElementById("CellStyleCheckbox");
169 gDialog.TextWrapCheckbox = document.getElementById("TextWrapCheckbox");
170 gDialog.CellColorCheckbox = document.getElementById("CellColorCheckbox");
171 gDialog.TableTab = document.getElementById("TableTab");
172 gDialog.CellTab = document.getElementById("CellTab");
173 gDialog.AdvancedEditCell = document.getElementById("AdvancedEditButton2");
174 // Save "normal" tooltip message for Advanced Edit button
175 gDialog.AdvancedEditCellToolTipText = gDialog.AdvancedEditCell.getAttribute("tooltiptext");
176
177 try {
178 gTableElement = gActiveEditor.getElementOrParentByTagName("table", null);
179 } catch (e) {}
180 if(!gTableElement)
181 {
182 dump("Failed to get table element!\n");
183 window.close();
184 return;
185 }
186 globalTableElement = gTableElement.cloneNode(false);
187
188 var tagNameObj = { value: "" };
189 var countObj = { value : 0 };
190 var tableOrCellElement;
191 try {
192 tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
193 } catch (e) {}
194
195 if (tagNameObj.value == "td")
196 {
197 // We are in a cell
198 gSelectedCellCount = countObj.value;
199 gCellElement = tableOrCellElement;
200 globalCellElement = gCellElement.cloneNode(false);
201
202 // Tells us whether cell, row, or column is selected
203 try {
204 gSelectedCellsType = gActiveEditor.getSelectedCellsType(gTableElement);
205 } catch (e) {}
206
207 // Ignore types except Cell, Row, and Column
208 if (gSelectedCellsType < SELECT_CELL || gSelectedCellsType > SELECT_COLUMN)
209 gSelectedCellsType = SELECT_CELL;
210
211 // Be sure at least 1 cell is selected.
212 // (If the count is 0, then we were inside the cell.)
213 if (gSelectedCellCount == 0)
214 DoCellSelection();
215
216 // Get location in the cell map
217 var rowIndexObj = { value: 0 };
218 var colIndexObj = { value: 0 };
219 try {
220 gActiveEditor.getCellIndexes(gCellElement, rowIndexObj, colIndexObj);
221 } catch (e) {}
222 gCurRowIndex = rowIndexObj.value;
223 gCurColIndex = colIndexObj.value;
224
225 // We save the current colspan to quickly
226 // move selection from from cell to cell
227 if (GetCellData(gCurRowIndex, gCurColIndex))
228 gCurColSpan = gCellData.colSpan;
229
230 // Starting TabPanel name is passed in
231 if (window.arguments[1] == "CellPanel")
232 gDialog.TabBox.selectedTab = gDialog.CellTab;
233 }
234
235 if (gDialog.TabBox.selectedTab == gDialog.TableTab)
236 {
237 // We may call this with table selected, but no cell,
238 // so disable the Cell Properties tab
239 if(!gCellElement)
240 {
241 // XXX: Disabling of tabs is currently broken, so for
242 // now we'll just remove the tab completely.
243 //gDialog.CellTab.disabled = true;
244 gDialog.CellTab.parentNode.removeChild(gDialog.CellTab);
245 }
246 }
247
248 // Note: we must use gTableElement, not globalTableElement for these,
249 // thus we should not put this in InitDialog.
250 // Instead, monitor desired counts with separate globals
251 var rowCountObj = { value: 0 };
252 var colCountObj = { value: 0 };
253 try {
254 gActiveEditor.getTableSize(gTableElement, rowCountObj, colCountObj);
255 } catch (e) {}
256
257 gRowCount = rowCountObj.value;
258 gLastRowIndex = gRowCount-1;
259 gColCount = colCountObj.value;
260 gLastColIndex = gColCount-1;
261
262
263 // Set appropriate icons and enable state for the Previous/Next buttons
264 SetSelectionButtons();
265
266 // If only one cell in table, disable change-selection widgets
267 if (gRowCount == 1 && gColCount == 1)
268 gDialog.SelectionList.setAttribute("disabled", "true");
269
270 // User can change these via textboxes
271 gNewRowCount = gRowCount;
272 gNewColCount = gColCount;
273
274 // This flag is used to control whether set check state
275 // on "set attribute" checkboxes
276 // (Advanced Edit dialog use calls InitDialog when done)
277 gAdvancedEditUsed = false;
278 InitDialog();
279 gAdvancedEditUsed = true;
280
281 // If first initializing, we really aren't changing anything
282 gCellDataChanged = false;
283
284 if (gDialog.TabBox.selectedTab == gDialog.CellTab)
285 setTimeout("gDialog.SelectionList.focus()", 0);
286 else
287 SetTextboxFocus(gDialog.TableRowsInput);
288
289 SetWindowLocation();
290 }
291
292
InitDialog
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
293 function InitDialog()
294 {
295 // Get Table attributes
296 gDialog.TableRowsInput.value = gRowCount;
297 gDialog.TableColumnsInput.value = gColCount;
298 gDialog.TableWidthInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "width", "TableWidthUnits", gPercent);
299 if (gUseCSS) {
300 gDialog.TableHeightInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "height",
301 "TableHeightUnits", gPercent);
302 }
303 gDialog.BorderWidthInput.value = globalTableElement.border;
304 gDialog.SpacingInput.value = globalTableElement.cellSpacing;
305 gDialog.PaddingInput.value = globalTableElement.cellPadding;
306
307 var marginLeft = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-left");
308 var marginRight = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-right");
309 var halign = marginLeft.toLowerCase() + " " + marginRight.toLowerCase();
310 if (halign == "center center" || halign == "auto auto")
311 gDialog.TableAlignList.value = "center";
312 else if (halign == "right right" || halign == "auto 0px")
313 gDialog.TableAlignList.value = "right";
314 else // Default = left
315 gDialog.TableAlignList.value = "left";
316
317 // Be sure to get caption from table in doc, not the copied "globalTableElement"
318 gTableCaptionElement = gTableElement.caption;
319 if (gTableCaptionElement)
320 {
321 var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side");
322 if (align != "bottom" && align != "left" && align != "right")
323 align = "top";
324 gDialog.TableCaptionList.value = align;
325 }
326
327 gTableColor = GetHTMLOrCSSStyleValue(globalTableElement, bgcolor, cssBackgroundColorStr);
328 gTableColor = ConvertRGBColorIntoHEXColor(gTableColor);
329 SetColor("tableBackgroundCW", gTableColor);
330
331 InitCellPanel();
332 }
333
InitCellPanel
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
334 function InitCellPanel()
335 {
336 // Get cell attributes
337 if (globalCellElement)
338 {
339 // This assumes order of items is Cell, Row, Column
340 gDialog.SelectionList.value = gSelectedCellsType;
341
342 var previousValue = gDialog.CellHeightInput.value;
343 gDialog.CellHeightInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "height", "CellHeightUnits", gPixel);
344 gDialog.CellHeightCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellHeightInput.value;
345
346 previousValue= gDialog.CellWidthInput.value;
347 gDialog.CellWidthInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "width", "CellWidthUnits", gPixel);
348 gDialog.CellWidthCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellWidthInput.value;
349
350 var previousIndex = gDialog.CellVAlignList.selectedIndex;
351 var valign = GetHTMLOrCSSStyleValue(globalCellElement, "valign", "vertical-align").toLowerCase();
352 if (valign == topStr || valign == bottomStr)
353 gDialog.CellVAlignList.value = valign;
354 else // Default = middle
355 gDialog.CellVAlignList.value = defVAlign;
356
357 gDialog.CellVAlignCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellVAlignList.selectedIndex;
358
359 previousIndex = gDialog.CellHAlignList.selectedIndex;
360
361 gAlignWasChar = false;
362
363 var halign = GetHTMLOrCSSStyleValue(globalCellElement, "align", "text-align").toLowerCase();
364 switch (halign)
365 {
366 case centerStr:
367 case rightStr:
368 case justifyStr:
369 gDialog.CellHAlignList.value = halign;
370 break;
371 case charStr:
372 // We don't support UI for this because layout doesn't work: bug 2212.
373 // Remember that's what they had so we don't change it
374 // unless they change the alignment by using the menulist
375 gAlignWasChar = true;
376 // Fall through to use show default alignment in menu
377 default:
378 // Default depends on cell type (TH is "center", TD is "left")
379 gDialog.CellHAlignList.value =
380 (globalCellElement.nodeName.toLowerCase() == "th") ? "center" : "left";
381 break;
382 }
383
384 gDialog.CellHAlignCheckbox.checked = gAdvancedEditUsed &&
385 previousIndex != gDialog.CellHAlignList.selectedIndex;
386
387 previousIndex = gDialog.CellStyleList.selectedIndex;
388 gDialog.CellStyleList.value = globalCellElement.nodeName.toLowerCase();
389 gDialog.CellStyleCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellStyleList.selectedIndex;
390
391 previousIndex = gDialog.TextWrapList.selectedIndex;
392 if (GetHTMLOrCSSStyleValue(globalCellElement, "nowrap", "white-space") == "nowrap")
393 gDialog.TextWrapList.value = "nowrap";
394 else
395 gDialog.TextWrapList.value = "wrap";
396 gDialog.TextWrapCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.TextWrapList.selectedIndex;
397
398 previousValue = gCellColor;
399 gCellColor = GetHTMLOrCSSStyleValue(globalCellElement, bgcolor, cssBackgroundColorStr);
400 gCellColor = ConvertRGBColorIntoHEXColor(gCellColor);
401 SetColor("cellBackgroundCW", gCellColor);
402 gDialog.CellColorCheckbox.checked = gAdvancedEditUsed && previousValue != gCellColor;
403
404 // We want to set this true in case changes came
405 // from Advanced Edit dialog session (must assume something changed)
406 gCellDataChanged = true;
407 }
408 }
409
GetCellData
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
410 function GetCellData(rowIndex, colIndex)
411 {
412 // Get actual rowspan and colspan
413 var startRowIndexObj = { value: 0 };
414 var startColIndexObj = { value: 0 };
415 var rowSpanObj = { value: 0 };
416 var colSpanObj = { value: 0 };
417 var actualRowSpanObj = { value: 0 };
418 var actualColSpanObj = { value: 0 };
419 var isSelectedObj = { value: false };
420
421 try {
422 gActiveEditor.getCellDataAt(gTableElement, rowIndex, colIndex,
423 gCellData,
424 startRowIndexObj, startColIndexObj,
425 rowSpanObj, colSpanObj,
426 actualRowSpanObj, actualColSpanObj, isSelectedObj);
427 // We didn't find a cell
428 if (!gCellData.value) return false;
429 }
430 catch(ex) {
431 return false;
432 }
433
434 gCellData.startRowIndex = startRowIndexObj.value;
435 gCellData.startColIndex = startColIndexObj.value;
436 gCellData.rowSpan = rowSpanObj.value;
437 gCellData.colSpan = colSpanObj.value;
438 gCellData.actualRowSpan = actualRowSpanObj.value;
439 gCellData.actualColSpan = actualColSpanObj.value;
440 gCellData.isSelected = isSelectedObj.value;
441 return true;
442 }
443
SelectCellHAlign
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
444 function SelectCellHAlign()
445 {
446 SetCheckbox("CellHAlignCheckbox");
447 // Once user changes the alignment,
448 // we lose their original "CharAt" alignment"
449 gAlignWasChar = false;
450 }
451
GetColorAndUpdate
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
452 function GetColorAndUpdate(ColorWellID)
453 {
454 var colorWell = document.getElementById(ColorWellID);
455 if (!colorWell) return;
456
457 var colorObj = { Type:"", TableColor:0, CellColor:0, NoDefault:false, Cancel:false, BackgroundColor:0 };
458
459 switch( ColorWellID )
460 {
461 case "tableBackgroundCW":
462 colorObj.Type = "Table";
463 colorObj.TableColor = gTableColor;
464 break;
465 case "cellBackgroundCW":
466 colorObj.Type = "Cell";
467 colorObj.CellColor = gCellColor;
468 break;
469 }
470 window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj);
471
472 // User canceled the dialog
473 if (colorObj.Cancel)
474 return;
475
476 switch( ColorWellID )
477 {
478 case "tableBackgroundCW":
479 gTableColor = colorObj.BackgroundColor;
480 SetColor(ColorWellID, gTableColor);
481 break;
482 case "cellBackgroundCW":
483 gCellColor = colorObj.BackgroundColor;
484 SetColor(ColorWellID, gCellColor);
485 SetCheckbox('CellColorCheckbox');
486 break;
487 }
488 }
489
SetColor
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
490 function SetColor(ColorWellID, color)
491 {
492 // Save the color
493 if (ColorWellID == "cellBackgroundCW")
494 {
495 if (color)
496 {
497 try {
498 gActiveEditor.setAttributeOrEquivalent(globalCellElement, bgcolor,
499 color, true);
500 } catch(e) {}
501 gDialog.CellInheritColor.collapsed = true;
502 }
503 else
504 {
505 try {
506 gActiveEditor.removeAttributeOrEquivalent(globalCellElement, bgcolor, true);
507 } catch(e) {}
508 // Reveal addition message explaining "default" color
509 gDialog.CellInheritColor.collapsed = false;
510 }
511 }
512 else
513 {
514 if (color)
515 {
516 try {
517 gActiveEditor.setAttributeOrEquivalent(globalTableElement, bgcolor,
518 color, true);
519 } catch(e) {}
520 gDialog.TableInheritColor.collapsed = true;
521 }
522 else
523 {
524 try {
525 gActiveEditor.removeAttributeOrEquivalent(globalTableElement, bgcolor, true);
526 } catch(e) {}
527 gDialog.TableInheritColor.collapsed = false;
528 }
529 SetCheckbox('CellColorCheckbox');
530 }
531
532 setColorWell(ColorWellID, color);
533 }
534
ChangeSelectionToFirstCell
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
535 function ChangeSelectionToFirstCell()
536 {
537 if (!GetCellData(0,0))
538 {
539 dump("Can't find first cell in table!\n");
540 return;
541 }
542 gCellElement = gCellData.value;
543 globalCellElement = gCellElement;
544
545 gCurRowIndex = 0;
546 gCurColIndex = 0;
547 ChangeSelection(RESET_SELECTION);
548 }
549
ChangeSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
550 function ChangeSelection(newType)
551 {
552 newType = Number(newType);
553
554 if (gSelectedCellsType == newType)
555 return;
556
557 if (newType == RESET_SELECTION)
558 // Restore selection to existing focus cell
559 gSelection.collapse(gCellElement,0);
560 else
561 gSelectedCellsType = newType;
562
563 // Keep the same focus gCellElement, just change the type
564 DoCellSelection();
565 SetSelectionButtons();
566
567 // Note: globalCellElement should still be a clone of gCellElement
568 }
569
MoveSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
570 function MoveSelection(forward)
571 {
572 var newRowIndex = gCurRowIndex;
573 var newColIndex = gCurColIndex;
574 var focusCell;
575 var inRow = false;
576
577 if (gSelectedCellsType == SELECT_ROW)
578 {
579 newRowIndex += (forward ? 1 : -1);
580
581 // Wrap around if before first or after last row
582 if (newRowIndex < 0)
583 newRowIndex = gLastRowIndex;
584 else if (newRowIndex > gLastRowIndex)
585 newRowIndex = 0;
586 inRow = true;
587
588 // Use first cell in row for focus cell
589 newColIndex = 0;
590 }
591 else
592 {
593 // Cell or column:
594 if (!forward)
595 newColIndex--;
596
597 if (gSelectedCellsType == SELECT_CELL)
598 {
599 // Skip to next cell
600 if (forward)
601 newColIndex += gCurColSpan;
602 }
603 else // SELECT_COLUMN
604 {
605 // Use first cell in column for focus cell
606 newRowIndex = 0;
607
608 // Don't skip by colspan,
609 // but find first cell in next cellmap column
610 if (forward)
611 newColIndex++;
612 }
613
614 if (newColIndex < 0)
615 {
616 // Request is before the first cell in column
617
618 // Wrap to last cell in column
619 newColIndex = gLastColIndex;
620
621 if (gSelectedCellsType == SELECT_CELL)
622 {
623 // If moving by cell, also wrap to previous...
624 if (newRowIndex > 0)
625 newRowIndex -= 1;
626 else
627 // ...or the last row
628 newRowIndex = gLastRowIndex;
629
630 inRow = true;
631 }
632 }
633 else if (newColIndex > gLastColIndex)
634 {
635 // Request is after the last cell in column
636
637 // Wrap to first cell in column
638 newColIndex = 0;
639
640 if (gSelectedCellsType == SELECT_CELL)
641 {
642 // If moving by cell, also wrap to next...
643 if (newRowIndex < gLastRowIndex)
644 newRowIndex++;
645 else
646 // ...or the first row
647 newRowIndex = 0;
648
649 inRow = true;
650 }
651 }
652 }
653
654 // Get the cell at the new location
655 do {
656 if (!GetCellData(newRowIndex, newColIndex))
657 {
658 dump("MoveSelection: CELL NOT FOUND\n");
659 return;
660 }
661 if (inRow)
662 {
663 if (gCellData.startRowIndex == newRowIndex)
664 break;
665 else
666 // Cell spans from a row above, look for the next cell in row
667 newRowIndex += gCellData.actualRowSpan;
668 }
669 else
670 {
671 if (gCellData.startColIndex == newColIndex)
672 break;
673 else
674 // Cell spans from a Col above, look for the next cell in column
675 newColIndex += gCellData.actualColSpan;
676 }
677 }
678 while(true);
679
680 // Save data for current selection before changing
681 if (gCellDataChanged) // && gDialog.ApplyBeforeMove.checked)
682 {
683 if (!ValidateCellData())
684 return;
685
686 gActiveEditor.beginTransaction();
687 // Apply changes to all selected cells
688 ApplyCellAttributes();
689 gActiveEditor.endTransaction();
690
691 SetCloseButton();
692 }
693
694 // Set cell and other data for new selection
695 gCellElement = gCellData.value;
696
697 // Save globals for new current cell
698 gCurRowIndex = gCellData.startRowIndex;
699 gCurColIndex = gCellData.startColIndex;
700 gCurColSpan = gCellData.actualColSpan;
701
702 // Copy for new global cell
703 globalCellElement = gCellElement.cloneNode(false);
704
705 // Change the selection
706 DoCellSelection();
707
708 // Scroll page so new selection is visible
709 // Using SELECTION_ANCHOR_REGION makes the upper-left corner of first selected cell
710 // the point to bring into view.
711 try {
712 var selectionController = gActiveEditor.selectionController;
713 selectionController.scrollSelectionIntoView(selectionController.SELECTION_NORMAL, selectionController.SELECTION_ANCHOR_REGION, true);
714 } catch (e) {}
715
716 // Reinitialize dialog using new cell
717 // if (!gDialog.KeepCurrentData.checked)
718 // Setting this false unchecks all "set attributes" checkboxes
719 gAdvancedEditUsed = false;
720 InitCellPanel();
721 gAdvancedEditUsed = true;
722 }
723
724
DoCellSelection
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
725 function DoCellSelection()
726 {
727 // Collapse selection into to the focus cell
728 // so editor uses that as start cell
729 gSelection.collapse(gCellElement, 0);
730
731 var tagNameObj = { value: "" };
732 var countObj = { value: 0 };
733 try {
734 switch (gSelectedCellsType)
735 {
736 case SELECT_CELL:
737 gActiveEditor.selectTableCell();
738 break
739 case SELECT_ROW:
740 gActiveEditor.selectTableRow();
741 break;
742 default:
743 gActiveEditor.selectTableColumn();
744 break;
745 }
746 // Get number of cells selected
747 var tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj);
748 } catch (e) {}
749
750 if (tagNameObj.value == "td")
751 gSelectedCellCount = countObj.value;
752 else
753 gSelectedCellCount = 0;
754
755 // Currently, we can only allow advanced editing on ONE cell element at a time
756 // else we ignore CSS, JS, and HTML attributes not already in dialog
757 SetElementEnabled(gDialog.AdvancedEditCell, gSelectedCellCount == 1);
758
759 gDialog.AdvancedEditCell.setAttribute("tooltiptext",
760 gSelectedCellCount > 1 ? GetString("AdvancedEditForCellMsg") :
761 gDialog.AdvancedEditCellToolTipText);
762 }
763
SetSelectionButtons
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
764 function SetSelectionButtons()
765 {
766 if (gSelectedCellsType == SELECT_ROW)
767 {
768 // Trigger CSS to set images of up and down arrows
769 gDialog.PreviousButton.setAttribute("type","row");
770 gDialog.NextButton.setAttribute("type","row");
771 }
772 else
773 {
774 // or images of left and right arrows
775 gDialog.PreviousButton.setAttribute("type","col");
776 gDialog.NextButton.setAttribute("type","col");
777 }
778 DisableSelectionButtons((gSelectedCellsType == SELECT_ROW && gRowCount == 1) ||
779 (gSelectedCellsType == SELECT_COLUMN && gColCount == 1) ||
780 (gRowCount == 1 && gColCount == 1));
781 }
782
DisableSelectionButtons
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
783 function DisableSelectionButtons( disable )
784 {
785 gDialog.PreviousButton.setAttribute("disabled", disable ? "true" : "false");
786 gDialog.NextButton.setAttribute("disabled", disable ? "true" : "false");
787 }
788
SwitchToValidatePanel
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
789 function SwitchToValidatePanel()
790 {
791 if (gDialog.TabBox.selectedTab != gValidateTab)
792 gDialog.TabBox.selectedTab = gValidateTab;
793 }
794
SetAlign
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
795 function SetAlign(listID, defaultValue, element, attName)
796 {
797 var value = document.getElementById(listID).value;
798 if (value == defaultValue)
799 {
800 try {
801 gActiveEditor.removeAttributeOrEquivalent(element, attName, true);
802 } catch(e) {}
803 }
804 else
805 {
806 try {
807 gActiveEditor.setAttributeOrEquivalent(element, attName, value, true);
808 } catch(e) {}
809 }
810 }
811
ValidateTableData
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
812 function ValidateTableData()
813 {
814 gValidateTab = gDialog.TableTab;
815 gNewRowCount = Number(ValidateNumber(gDialog.TableRowsInput, null, 1, gMaxRows, null, true, true));
816 if (gValidationError) return false;
817
818 gNewColCount = Number(ValidateNumber(gDialog.TableColumnsInput, null, 1, gMaxColumns, null, true, true));
819 if (gValidationError) return false;
820
821 // If user is deleting any cells, get confirmation
822 // (This is a global to the dialog and we ask only once per dialog session)
823 if ( !gCanDelete &&
824 (gNewRowCount < gRowCount ||
825 gNewColCount < gColCount) )
826 {
827 if (ConfirmWithTitle(GetString("DeleteTableTitle"),
828 GetString("DeleteTableMsg"),
829 GetString("DeleteCells")) )
830 {
831 gCanDelete = true;
832 }
833 else
834 {
835 SetTextboxFocus(gNewRowCount < gRowCount ? gDialog.TableRowsInput : gDialog.TableColumnsInput);
836 return false;
837 }
838 }
839
840 ValidateNumber(gDialog.TableWidthInput, gDialog.TableWidthUnits,
841 1, gMaxTableSize, globalTableElement, "width");
842 if (gValidationError) return false;
843
844 if (gUseCSS) {
845 ValidateNumber(gDialog.TableHeightInput, gDialog.TableHeightUnits,
846 1, gMaxTableSize, globalTableElement, "height");
847 if (gValidationError) return false;
848 }
849
850 var border = ValidateNumber(gDialog.BorderWidthInput, null, 0, gMaxPixels, globalTableElement, "border");
851 // TODO: Deal with "BORDER" without value issue
852 if (gValidationError) return false;
853
854 ValidateNumber(gDialog.SpacingInput, null, 0, gMaxPixels, globalTableElement, "cellspacing");
855 if (gValidationError) return false;
856
857 ValidateNumber(gDialog.PaddingInput, null, 0, gMaxPixels, globalTableElement, "cellpadding");
858 if (gValidationError) return false;
859
860 SetAlign("TableAlignList", defHAlign, globalTableElement, "align");
861
862 // Color is set on globalCellElement immediately
863 return true;
864 }
865
ValidateCellData
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
866 function ValidateCellData()
867 {
868
869 gValidateTab = gDialog.CellTab;
870
871 if (gDialog.CellHeightCheckbox.checked)
872 {
873 ValidateNumber(gDialog.CellHeightInput, gDialog.CellHeightUnits,
874 1, gMaxTableSize, globalCellElement, "height");
875 if (gValidationError) return false;
876 }
877
878 if (gDialog.CellWidthCheckbox.checked)
879 {
880 ValidateNumber(gDialog.CellWidthInput, gDialog.CellWidthUnits,
881 1, gMaxTableSize, globalCellElement, "width");
882 if (gValidationError) return false;
883 }
884
885 if (gDialog.CellHAlignCheckbox.checked)
886 {
887 var hAlign = gDialog.CellHAlignList.value;
888
889 // Horizontal alignment is complicated by "char" type
890 // We don't change current values if user didn't edit alignment
891 if (!gAlignWasChar)
892 {
893 globalCellElement.removeAttribute(charStr);
894
895 // Always set "align" attribute,
896 // so the default "left" is effective in a cell
897 // when parent row has align set.
898 globalCellElement.setAttribute("align", hAlign);
899 }
900 }
901
902 if (gDialog.CellVAlignCheckbox.checked)
903 {
904 // Always set valign (no default in 2nd param) so
905 // the default "middle" is effective in a cell
906 // when parent row has valign set.
907 SetAlign("CellVAlignList", "", globalCellElement, "valign");
908 }
909
910 if (gDialog.TextWrapCheckbox.checked)
911 {
912 if (gDialog.TextWrapList.value == "nowrap")
913 try {
914 gActiveEditor.setAttributeOrEquivalent(globalCellElement, "nowrap",
915 "nowrap", true);
916 } catch(e) {}
917 else
918 try {
919 gActiveEditor.removeAttributeOrEquivalent(globalCellElement, "nowrap", true);
920 } catch(e) {}
921 }
922
923 return true;
924 }
925
ValidateData
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
926 function ValidateData()
927 {
928 var result;
929
930 // Validate current panel first
931 if (gDialog.TabBox.selectedTab == gDialog.TableTab)
932 {
933 result = ValidateTableData();
934 if (result)
935 result = ValidateCellData();
936 } else {
937 result = ValidateCellData();
938 if (result)
939 result = ValidateTableData();
940 }
941 if(!result) return false;
942
943 // Set global element for AdvancedEdit
944 if(gDialog.TabBox.selectedTab == gDialog.TableTab)
945 globalElement = globalTableElement;
946 else
947 globalElement = globalCellElement;
948
949 return true;
950 }
951
ChangeCellTextbox
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
952 function ChangeCellTextbox(textboxID)
953 {
954 // Filter input for just integers
955 forceInteger(textboxID);
956
957 if (gDialog.TabBox.selectedTab == gDialog.CellTab)
958 gCellDataChanged = true;
959 }
960
961 // Call this when a textbox or menulist is changed
962 // so the checkbox is automatically set
SetCheckbox
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
963 function SetCheckbox(checkboxID)
964 {
965 if (checkboxID && checkboxID.length > 0)
966 {
967 // Set associated checkbox
968 document.getElementById(checkboxID).checked = true;
969 }
970 gCellDataChanged = true;
971 }
972
ChangeIntTextbox
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
973 function ChangeIntTextbox(textboxID, checkboxID)
974 {
975 // Filter input for just integers
976 forceInteger(textboxID);
977
978 // Set associated checkbox
979 SetCheckbox(checkboxID);
980 }
981
CloneAttribute
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
982 function CloneAttribute(destElement, srcElement, attr)
983 {
984 var value = srcElement.getAttribute(attr);
985 // Use editor methods since we are always
986 // modifying a table in the document and
987 // we need transaction system for undo
988 try {
989 if (!value || value.length == 0)
990 gActiveEditor.removeAttributeOrEquivalent(destElement, attr, false);
991 else
992 gActiveEditor.setAttributeOrEquivalent(destElement, attr, value, false);
993 } catch(e) {}
994 }
995
ApplyTableAttributes
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
996 function ApplyTableAttributes()
997 {
998 var newAlign = gDialog.TableCaptionList.value;
999 if (!newAlign) newAlign = "";
1000
1001 if (gTableCaptionElement)
1002 {
1003 // Get current alignment
1004 var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side").toLowerCase();
1005 // This is the default
1006 if (!align) align = "top";
1007
1008 if (newAlign == "")
1009 {
1010 // Remove existing caption
1011 try {
1012 gActiveEditor.deleteNode(gTableCaptionElement);
1013 } catch(e) {}
1014 gTableCaptionElement = null;
1015 }
1016 else if(newAlign != align)
1017 {
1018 try {
1019 if (newAlign == "top") // This is default, so don't explicitly set it
1020 gActiveEditor.removeAttributeOrEquivalent(gTableCaptionElement, "align", false);
1021 else
1022 gActiveEditor.setAttributeOrEquivalent(gTableCaptionElement, "align", newAlign, false);
1023 } catch(e) {}
1024 }
1025 }
1026 else if (newAlign != "")
1027 {
1028 // Create and insert a caption:
1029 try {
1030 gTableCaptionElement = gActiveEditor.createElementWithDefaults("caption");
1031 } catch (e) {}
1032 if (gTableCaptionElement)
1033 {
1034 if (newAlign != "top")
1035 gTableCaptionElement.setAttribute("align", newAlign);
1036
1037 // Insert it into the table - caption is always inserted as first child
1038 try {
1039 gActiveEditor.insertNode(gTableCaptionElement, gTableElement, 0);
1040 } catch(e) {}
1041
1042 // Put selecton back where it was
1043 ChangeSelection(RESET_SELECTION);
1044 }
1045 }
1046
1047 var countDelta;
1048 var foundCell;
1049 var i;
1050
1051 if (gNewRowCount != gRowCount)
1052 {
1053 countDelta = gNewRowCount - gRowCount;
1054 if (gNewRowCount > gRowCount)
1055 {
1056 // Append new rows
1057 // Find first cell in last row
1058 if(GetCellData(gLastRowIndex, 0))
1059 {
1060 try {
1061 // Move selection to the last cell
1062 gSelection.collapse(gCellData.value,0);
1063 // Insert new rows after it
1064 gActiveEditor.insertTableRow(countDelta, true);
1065 gRowCount = gNewRowCount;
1066 gLastRowIndex = gRowCount - 1;
1067 // Put selecton back where it was
1068 ChangeSelection(RESET_SELECTION);
1069 }
1070 catch(ex) {
1071 dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
1072 }
1073 }
1074 }
1075 else
1076 {
1077 // Delete rows
1078 if (gCanDelete)
1079 {
1080 // Find first cell starting in first row we delete
1081 var firstDeleteRow = gRowCount + countDelta;
1082 foundCell = false;
1083 for ( i = 0; i <= gLastColIndex; i++)
1084 {
1085 if (!GetCellData(firstDeleteRow, i))
1086 break; // We failed to find a cell
1087
1088 if (gCellData.startRowIndex == firstDeleteRow)
1089 {
1090 foundCell = true;
1091 break;
1092 }
1093 };
1094 if (foundCell)
1095 {
1096 try {
1097 // Move selection to the cell we found
1098 gSelection.collapse(gCellData.value, 0);
1099 gActiveEditor.deleteTableRow(-countDelta);
1100 gRowCount = gNewRowCount;
1101 gLastRowIndex = gRowCount - 1;
1102 if (gCurRowIndex > gLastRowIndex)
1103 // We are deleting our selection
1104 // move it to start of table
1105 ChangeSelectionToFirstCell()
1106 else
1107 // Put selecton back where it was
1108 ChangeSelection(RESET_SELECTION);
1109 }
1110 catch(ex) {
1111 dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
1112 }
1113 }
1114 }
1115 }
1116 }
1117
1118 if (gNewColCount != gColCount)
1119 {
1120 countDelta = gNewColCount - gColCount;
1121
1122 if (gNewColCount > gColCount)
1123 {
1124 // Append new columns
1125 // Find last cell in first column
1126 if(GetCellData(0, gLastColIndex))
1127 {
1128 try {
1129 // Move selection to the last cell
1130 gSelection.collapse(gCellData.value,0);
1131 gActiveEditor.insertTableColumn(countDelta, true);
1132 gColCount = gNewColCount;
1133 gLastColIndex = gColCount-1;
1134 // Restore selection
1135 ChangeSelection(RESET_SELECTION);
1136 }
1137 catch(ex) {
1138 dump("FAILED TO FIND FIRST CELL IN LAST COLUMN\n");
1139 }
1140 }
1141 }
1142 else
1143 {
1144 // Delete columns
1145 if (gCanDelete)
1146 {
1147 var firstDeleteCol = gColCount + countDelta;
1148 foundCell = false;
1149 for ( i = 0; i <= gLastRowIndex; i++)
1150 {
1151 // Find first cell starting in first column we delete
1152 if (!GetCellData(i, firstDeleteCol))
1153 break; // We failed to find a cell
1154
1155 if (gCellData.startColIndex == firstDeleteCol)
1156 {
1157 foundCell = true;
1158 break;
1159 }
1160 };
1161 if (foundCell)
1162 {
1163 try {
1164 // Move selection to the cell we found
1165 gSelection.collapse(gCellData.value, 0);
1166 gActiveEditor.deleteTableColumn(-countDelta);
1167 gColCount = gNewColCount;
1168 gLastColIndex = gColCount-1;
1169 if (gCurColIndex > gLastColIndex)
1170 ChangeSelectionToFirstCell()
1171 else
1172 ChangeSelection(RESET_SELECTION);
1173 }
1174 catch(ex) {
1175 dump("FAILED TO FIND FIRST CELL IN LAST ROW\n");
1176 }
1177 }
1178 }
1179 }
1180 }
1181
1182 // Clone all remaining attributes to pick up
1183 // anything changed by Advanced Edit Dialog
1184 try {
1185 gActiveEditor.cloneAttributes(gTableElement, globalTableElement);
1186 } catch(e) {}
1187 }
1188
ApplyCellAttributes
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1189 function ApplyCellAttributes()
1190 {
1191 var rangeObj = { value: null };
1192 var selectedCell;
1193 try {
1194 selectedCell = gActiveEditor.getFirstSelectedCell(rangeObj);
1195 } catch(e) {}
1196
1197 if (!selectedCell)
1198 return;
1199
1200 if (gSelectedCellCount == 1)
1201 {
1202 // When only one cell is selected, simply clone entire element,
1203 // thus CSS and JS from Advanced edit is copied
1204 try {
1205 gActiveEditor.cloneAttributes(selectedCell, globalCellElement);
1206 } catch(e) {}
1207
1208 if (gDialog.CellStyleCheckbox.checked)
1209 {
1210 var currentStyleIndex = (selectedCell.nodeName.toLowerCase() == "th") ? 1 : 0;
1211 if (gDialog.CellStyleList.selectedIndex != currentStyleIndex)
1212 {
1213 // Switch cell types
1214 // (replaces with new cell and copies attributes and contents)
1215 try {
1216 selectedCell = gActiveEditor.switchTableCellHeaderType(selectedCell);
1217 } catch(e) {}
1218 }
1219 }
1220 }
1221 else
1222 {
1223 // Apply changes to all selected cells
1224 //XXX THIS DOESN'T COPY ADVANCED EDIT CHANGES!
1225 try {
1226 while (selectedCell)
1227 {
1228 ApplyAttributesToOneCell(selectedCell);
1229 selectedCell = gActiveEditor.getNextSelectedCell(rangeObj);
1230 }
1231 } catch(e) {}
1232 }
1233 gCellDataChanged = false;
1234 }
1235
ApplyAttributesToOneCell
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1236 function ApplyAttributesToOneCell(destElement)
1237 {
1238 if (gDialog.CellHeightCheckbox.checked)
1239 CloneAttribute(destElement, globalCellElement, "height");
1240
1241 if (gDialog.CellWidthCheckbox.checked)
1242 CloneAttribute(destElement, globalCellElement, "width");
1243
1244 if (gDialog.CellHAlignCheckbox.checked)
1245 {
1246 CloneAttribute(destElement, globalCellElement, "align");
1247 CloneAttribute(destElement, globalCellElement, charStr);
1248 }
1249
1250 if (gDialog.CellVAlignCheckbox.checked)
1251 CloneAttribute(destElement, globalCellElement, "valign");
1252
1253 if (gDialog.TextWrapCheckbox.checked)
1254 CloneAttribute(destElement, globalCellElement, "nowrap");
1255
1256 if (gDialog.CellStyleCheckbox.checked)
1257 {
1258 var newStyleIndex = gDialog.CellStyleList.selectedIndex;
1259 var currentStyleIndex = (destElement.nodeName.toLowerCase() == "th") ? 1 : 0;
1260
1261 if (newStyleIndex != currentStyleIndex)
1262 {
1263 // Switch cell types
1264 // (replaces with new cell and copies attributes and contents)
1265 try {
1266 destElement = gActiveEditor.switchTableCellHeaderType(destElement);
1267 } catch(e) {}
1268 }
1269 }
1270
1271 if (gDialog.CellColorCheckbox.checked)
1272 CloneAttribute(destElement, globalCellElement, "bgcolor");
1273 }
1274
SetCloseButton
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1275 function SetCloseButton()
1276 {
1277 // Change text on "Cancel" button after Apply is used
1278 if (!gApplyUsed)
1279 {
1280 document.documentElement.setAttribute("buttonlabelcancel",
1281 document.documentElement.getAttribute("buttonlabelclose"));
1282 gApplyUsed = true;
1283 }
1284 }
1285
Apply
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1286 function Apply()
1287 {
1288 if (ValidateData())
1289 {
1290 gActiveEditor.beginTransaction();
1291
1292 ApplyTableAttributes();
1293
1294 // We may have just a table, so check for cell element
1295 if (globalCellElement)
1296 ApplyCellAttributes();
1297
1298 gActiveEditor.endTransaction();
1299
1300 SetCloseButton();
1301 return true;
1302 }
1303 return false;
1304 }
1305
onAccept
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1306 function onAccept()
1307 {
1308 // Do same as Apply and close window if ValidateData succeeded
1309 var retVal = Apply();
1310 if (retVal)
1311 SaveWindowLocation();
1312
1313 return retVal;
1314 }