/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Ben Goodger * Charles Manske (cmanske@netscape.com) * Neil Rashbrook (neil@parkwaycc.co.uk) * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ //Cancel() is in EdDialogCommon.js var gTableElement; var gCellElement; var gTableCaptionElement; var globalCellElement; var globalTableElement var gValidateTab; const defHAlign = "left"; const centerStr = "center"; //Index=1 const rightStr = "right"; // 2 const justifyStr = "justify"; // 3 const charStr = "char"; // 4 const defVAlign = "middle"; const topStr = "top"; const bottomStr = "bottom"; const bgcolor = "bgcolor"; var gTableColor; var gCellColor; const cssBackgroundColorStr = "background-color"; var gRowCount = 1; var gColCount = 1; var gLastRowIndex; var gLastColIndex; var gNewRowCount; var gNewColCount; var gCurRowIndex; var gCurColIndex; var gCurColSpan; var gSelectedCellsType = 1; const SELECT_CELL = 1; const SELECT_ROW = 2; const SELECT_COLUMN = 3; const RESET_SELECTION = 0; var gCellData = { value:null, startRowIndex:0, startColIndex:0, rowSpan:0, colSpan:0, actualRowSpan:0, actualColSpan:0, isSelected:false }; var gAdvancedEditUsed; var gAlignWasChar = false; /* From C++: 0 TABLESELECTION_TABLE 1 TABLESELECTION_CELL There are 1 or more cells selected but complete rows or columns are not selected 2 TABLESELECTION_ROW All cells are in 1 or more rows and in each row, all cells selected Note: This is the value if all rows (thus all cells) are selected 3 TABLESELECTION_COLUMN All cells are in 1 or more columns */ var gSelectedCellCount = 0; var gApplyUsed = false; var gSelection; var gCellDataChanged = false; var gCanDelete = false; var gPrefs = GetPrefs(); var gUseCSS = true; var gActiveEditor; // dialog initialization code function Startup() { gActiveEditor = GetCurrentTableEditor(); if (!gActiveEditor) { window.close(); return; } try { gSelection = gActiveEditor.selection; } catch (e) {} if (!gSelection) return; // Get dialog widgets - Table Panel gDialog.TableRowsInput = document.getElementById("TableRowsInput"); gDialog.TableColumnsInput = document.getElementById("TableColumnsInput"); gDialog.TableWidthInput = document.getElementById("TableWidthInput"); gDialog.TableWidthUnits = document.getElementById("TableWidthUnits"); gDialog.TableHeightInput = document.getElementById("TableHeightInput"); gDialog.TableHeightUnits = document.getElementById("TableHeightUnits"); try { if (!gPrefs.getBoolPref("editor.use_css") || (gActiveEditor.flags & 1)) { gUseCSS = false; var tableHeightLabel = document.getElementById("TableHeightLabel"); tableHeightLabel.parentNode.removeChild(tableHeightLabel); gDialog.TableHeightInput.parentNode.removeChild(gDialog.TableHeightInput); gDialog.TableHeightUnits.parentNode.removeChild(gDialog.TableHeightUnits); } } catch (e) {} gDialog.BorderWidthInput = document.getElementById("BorderWidthInput"); gDialog.SpacingInput = document.getElementById("SpacingInput"); gDialog.PaddingInput = document.getElementById("PaddingInput"); gDialog.TableAlignList = document.getElementById("TableAlignList"); gDialog.TableCaptionList = document.getElementById("TableCaptionList"); gDialog.TableInheritColor = document.getElementById("TableInheritColor"); gDialog.TabBox = document.getElementById("TabBox"); // Cell Panel gDialog.SelectionList = document.getElementById("SelectionList"); gDialog.PreviousButton = document.getElementById("PreviousButton"); gDialog.NextButton = document.getElementById("NextButton"); // Currently, we always apply changes and load new attributes when changing selection // (Let's keep this for possible future use) //gDialog.ApplyBeforeMove = document.getElementById("ApplyBeforeMove"); //gDialog.KeepCurrentData = document.getElementById("KeepCurrentData"); gDialog.CellHeightInput = document.getElementById("CellHeightInput"); gDialog.CellHeightUnits = document.getElementById("CellHeightUnits"); gDialog.CellWidthInput = document.getElementById("CellWidthInput"); gDialog.CellWidthUnits = document.getElementById("CellWidthUnits"); gDialog.CellHAlignList = document.getElementById("CellHAlignList"); gDialog.CellVAlignList = document.getElementById("CellVAlignList"); gDialog.CellInheritColor = document.getElementById("CellInheritColor"); gDialog.CellStyleList = document.getElementById("CellStyleList"); gDialog.TextWrapList = document.getElementById("TextWrapList"); // In cell panel, user must tell us which attributes to apply via checkboxes, // else we would apply values from one cell to ALL in selection // and that's probably not what they expect! gDialog.CellHeightCheckbox = document.getElementById("CellHeightCheckbox"); gDialog.CellWidthCheckbox = document.getElementById("CellWidthCheckbox"); gDialog.CellHAlignCheckbox = document.getElementById("CellHAlignCheckbox"); gDialog.CellVAlignCheckbox = document.getElementById("CellVAlignCheckbox"); gDialog.CellStyleCheckbox = document.getElementById("CellStyleCheckbox"); gDialog.TextWrapCheckbox = document.getElementById("TextWrapCheckbox"); gDialog.CellColorCheckbox = document.getElementById("CellColorCheckbox"); gDialog.TableTab = document.getElementById("TableTab"); gDialog.CellTab = document.getElementById("CellTab"); gDialog.AdvancedEditCell = document.getElementById("AdvancedEditButton2"); // Save "normal" tooltip message for Advanced Edit button gDialog.AdvancedEditCellToolTipText = gDialog.AdvancedEditCell.getAttribute("tooltiptext"); try { gTableElement = gActiveEditor.getElementOrParentByTagName("table", null); } catch (e) {} if(!gTableElement) { dump("Failed to get table element!\n"); window.close(); return; } globalTableElement = gTableElement.cloneNode(false); var tagNameObj = { value: "" }; var countObj = { value : 0 }; var tableOrCellElement; try { tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj); } catch (e) {} if (tagNameObj.value == "td") { // We are in a cell gSelectedCellCount = countObj.value; gCellElement = tableOrCellElement; globalCellElement = gCellElement.cloneNode(false); // Tells us whether cell, row, or column is selected try { gSelectedCellsType = gActiveEditor.getSelectedCellsType(gTableElement); } catch (e) {} // Ignore types except Cell, Row, and Column if (gSelectedCellsType < SELECT_CELL || gSelectedCellsType > SELECT_COLUMN) gSelectedCellsType = SELECT_CELL; // Be sure at least 1 cell is selected. // (If the count is 0, then we were inside the cell.) if (gSelectedCellCount == 0) DoCellSelection(); // Get location in the cell map var rowIndexObj = { value: 0 }; var colIndexObj = { value: 0 }; try { gActiveEditor.getCellIndexes(gCellElement, rowIndexObj, colIndexObj); } catch (e) {} gCurRowIndex = rowIndexObj.value; gCurColIndex = colIndexObj.value; // We save the current colspan to quickly // move selection from from cell to cell if (GetCellData(gCurRowIndex, gCurColIndex)) gCurColSpan = gCellData.colSpan; // Starting TabPanel name is passed in if (window.arguments[1] == "CellPanel") gDialog.TabBox.selectedTab = gDialog.CellTab; } if (gDialog.TabBox.selectedTab == gDialog.TableTab) { // We may call this with table selected, but no cell, // so disable the Cell Properties tab if(!gCellElement) { // XXX: Disabling of tabs is currently broken, so for // now we'll just remove the tab completely. //gDialog.CellTab.disabled = true; gDialog.CellTab.parentNode.removeChild(gDialog.CellTab); } } // Note: we must use gTableElement, not globalTableElement for these, // thus we should not put this in InitDialog. // Instead, monitor desired counts with separate globals var rowCountObj = { value: 0 }; var colCountObj = { value: 0 }; try { gActiveEditor.getTableSize(gTableElement, rowCountObj, colCountObj); } catch (e) {} gRowCount = rowCountObj.value; gLastRowIndex = gRowCount-1; gColCount = colCountObj.value; gLastColIndex = gColCount-1; // Set appropriate icons and enable state for the Previous/Next buttons SetSelectionButtons(); // If only one cell in table, disable change-selection widgets if (gRowCount == 1 && gColCount == 1) gDialog.SelectionList.setAttribute("disabled", "true"); // User can change these via textboxes gNewRowCount = gRowCount; gNewColCount = gColCount; // This flag is used to control whether set check state // on "set attribute" checkboxes // (Advanced Edit dialog use calls InitDialog when done) gAdvancedEditUsed = false; InitDialog(); gAdvancedEditUsed = true; // If first initializing, we really aren't changing anything gCellDataChanged = false; if (gDialog.TabBox.selectedTab == gDialog.CellTab) setTimeout("gDialog.SelectionList.focus()", 0); else SetTextboxFocus(gDialog.TableRowsInput); SetWindowLocation(); } function InitDialog() { // Get Table attributes gDialog.TableRowsInput.value = gRowCount; gDialog.TableColumnsInput.value = gColCount; gDialog.TableWidthInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "width", "TableWidthUnits", gPercent); if (gUseCSS) { gDialog.TableHeightInput.value = InitPixelOrPercentMenulist(globalTableElement, gTableElement, "height", "TableHeightUnits", gPercent); } gDialog.BorderWidthInput.value = globalTableElement.border; gDialog.SpacingInput.value = globalTableElement.cellSpacing; gDialog.PaddingInput.value = globalTableElement.cellPadding; var marginLeft = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-left"); var marginRight = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-right"); var halign = marginLeft.toLowerCase() + " " + marginRight.toLowerCase(); if (halign == "center center" || halign == "auto auto") gDialog.TableAlignList.value = "center"; else if (halign == "right right" || halign == "auto 0px") gDialog.TableAlignList.value = "right"; else // Default = left gDialog.TableAlignList.value = "left"; // Be sure to get caption from table in doc, not the copied "globalTableElement" gTableCaptionElement = gTableElement.caption; if (gTableCaptionElement) { var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side"); if (align != "bottom" && align != "left" && align != "right") align = "top"; gDialog.TableCaptionList.value = align; } gTableColor = GetHTMLOrCSSStyleValue(globalTableElement, bgcolor, cssBackgroundColorStr); gTableColor = ConvertRGBColorIntoHEXColor(gTableColor); SetColor("tableBackgroundCW", gTableColor); InitCellPanel(); } function InitCellPanel() { // Get cell attributes if (globalCellElement) { // This assumes order of items is Cell, Row, Column gDialog.SelectionList.value = gSelectedCellsType; var previousValue = gDialog.CellHeightInput.value; gDialog.CellHeightInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "height", "CellHeightUnits", gPixel); gDialog.CellHeightCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellHeightInput.value; previousValue= gDialog.CellWidthInput.value; gDialog.CellWidthInput.value = InitPixelOrPercentMenulist(globalCellElement, gCellElement, "width", "CellWidthUnits", gPixel); gDialog.CellWidthCheckbox.checked = gAdvancedEditUsed && previousValue != gDialog.CellWidthInput.value; var previousIndex = gDialog.CellVAlignList.selectedIndex; var valign = GetHTMLOrCSSStyleValue(globalCellElement, "valign", "vertical-align").toLowerCase(); if (valign == topStr || valign == bottomStr) gDialog.CellVAlignList.value = valign; else // Default = middle gDialog.CellVAlignList.value = defVAlign; gDialog.CellVAlignCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellVAlignList.selectedIndex; previousIndex = gDialog.CellHAlignList.selectedIndex; gAlignWasChar = false; var halign = GetHTMLOrCSSStyleValue(globalCellElement, "align", "text-align").toLowerCase(); switch (halign) { case centerStr: case rightStr: case justifyStr: gDialog.CellHAlignList.value = halign; break; case charStr: // We don't support UI for this because layout doesn't work: bug 2212. // Remember that's what they had so we don't change it // unless they change the alignment by using the menulist gAlignWasChar = true; // Fall through to use show default alignment in menu default: // Default depends on cell type (TH is "center", TD is "left") gDialog.CellHAlignList.value = (globalCellElement.nodeName.toLowerCase() == "th") ? "center" : "left"; break; } gDialog.CellHAlignCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellHAlignList.selectedIndex; previousIndex = gDialog.CellStyleList.selectedIndex; gDialog.CellStyleList.value = globalCellElement.nodeName.toLowerCase(); gDialog.CellStyleCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.CellStyleList.selectedIndex; previousIndex = gDialog.TextWrapList.selectedIndex; if (GetHTMLOrCSSStyleValue(globalCellElement, "nowrap", "white-space") == "nowrap") gDialog.TextWrapList.value = "nowrap"; else gDialog.TextWrapList.value = "wrap"; gDialog.TextWrapCheckbox.checked = gAdvancedEditUsed && previousIndex != gDialog.TextWrapList.selectedIndex; previousValue = gCellColor; gCellColor = GetHTMLOrCSSStyleValue(globalCellElement, bgcolor, cssBackgroundColorStr); gCellColor = ConvertRGBColorIntoHEXColor(gCellColor); SetColor("cellBackgroundCW", gCellColor); gDialog.CellColorCheckbox.checked = gAdvancedEditUsed && previousValue != gCellColor; // We want to set this true in case changes came // from Advanced Edit dialog session (must assume something changed) gCellDataChanged = true; } } function GetCellData(rowIndex, colIndex) { // Get actual rowspan and colspan var startRowIndexObj = { value: 0 }; var startColIndexObj = { value: 0 }; var rowSpanObj = { value: 0 }; var colSpanObj = { value: 0 }; var actualRowSpanObj = { value: 0 }; var actualColSpanObj = { value: 0 }; var isSelectedObj = { value: false }; try { gActiveEditor.getCellDataAt(gTableElement, rowIndex, colIndex, gCellData, startRowIndexObj, startColIndexObj, rowSpanObj, colSpanObj, actualRowSpanObj, actualColSpanObj, isSelectedObj); // We didn't find a cell if (!gCellData.value) return false; } catch(ex) { return false; } gCellData.startRowIndex = startRowIndexObj.value; gCellData.startColIndex = startColIndexObj.value; gCellData.rowSpan = rowSpanObj.value; gCellData.colSpan = colSpanObj.value; gCellData.actualRowSpan = actualRowSpanObj.value; gCellData.actualColSpan = actualColSpanObj.value; gCellData.isSelected = isSelectedObj.value; return true; } function SelectCellHAlign() { SetCheckbox("CellHAlignCheckbox"); // Once user changes the alignment, // we loose their original "CharAt" alignment" gAlignWasChar = false; } function GetColorAndUpdate(ColorWellID) { var colorWell = document.getElementById(ColorWellID); if (!colorWell) return; var colorObj = { Type:"", TableColor:0, CellColor:0, NoDefault:false, Cancel:false, BackgroundColor:0 }; switch( ColorWellID ) { case "tableBackgroundCW": colorObj.Type = "Table"; colorObj.TableColor = gTableColor; break; case "cellBackgroundCW": colorObj.Type = "Cell"; colorObj.CellColor = gCellColor; break; } window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj); // User canceled the dialog if (colorObj.Cancel) return; switch( ColorWellID ) { case "tableBackgroundCW": gTableColor = colorObj.BackgroundColor; SetColor(ColorWellID, gTableColor); break; case "cellBackgroundCW": gCellColor = colorObj.BackgroundColor; SetColor(ColorWellID, gCellColor); SetCheckbox('CellColorCheckbox'); break; } } function SetColor(ColorWellID, color) { // Save the color if (ColorWellID == "cellBackgroundCW") { if (color) { try { gActiveEditor.setAttributeOrEquivalent(globalCellElement, bgcolor, color, true); } catch(e) {} gDialog.CellInheritColor.collapsed = true; } else { try { gActiveEditor.removeAttributeOrEquivalent(globalCellElement, bgcolor, true); } catch(e) {} // Reveal addition message explaining "default" color gDialog.CellInheritColor.collapsed = false; } } else { if (color) { try { gActiveEditor.setAttributeOrEquivalent(globalTableElement, bgcolor, color, true); } catch(e) {} gDialog.TableInheritColor.collapsed = true; } else { try { gActiveEditor.removeAttributeOrEquivalent(globalTableElement, bgcolor, true); } catch(e) {} gDialog.TableInheritColor.collapsed = false; } SetCheckbox('CellColorCheckbox'); } setColorWell(ColorWellID, color); } function ChangeSelectionToFirstCell() { if (!GetCellData(0,0)) { dump("Can't find first cell in table!\n"); return; } gCellElement = gCellData.value; globalCellElement = gCellElement; gCurRowIndex = 0; gCurColIndex = 0; ChangeSelection(RESET_SELECTION); } function ChangeSelection(newType) { newType = Number(newType); if (gSelectedCellsType == newType) return; if (newType == RESET_SELECTION) // Restore selection to existing focus cell gSelection.collapse(gCellElement,0); else gSelectedCellsType = newType; // Keep the same focus gCellElement, just change the type DoCellSelection(); SetSelectionButtons(); // Note: globalCellElement should still be a clone of gCellElement } function MoveSelection(forward) { var newRowIndex = gCurRowIndex; var newColIndex = gCurColIndex; var focusCell; var inRow = false; if (gSelectedCellsType == SELECT_ROW) { newRowIndex += (forward ? 1 : -1); // Wrap around if before first or after last row if (newRowIndex < 0) newRowIndex = gLastRowIndex; else if (newRowIndex > gLastRowIndex) newRowIndex = 0; inRow = true; // Use first cell in row for focus cell newColIndex = 0; } else { // Cell or column: if (!forward) newColIndex--; if (gSelectedCellsType == SELECT_CELL) { // Skip to next cell if (forward) newColIndex += gCurColSpan; } else // SELECT_COLUMN { // Use first cell in column for focus cell newRowIndex = 0; // Don't skip by colspan, // but find first cell in next cellmap column if (forward) newColIndex++; } if (newColIndex < 0) { // Request is before the first cell in column // Wrap to last cell in column newColIndex = gLastColIndex; if (gSelectedCellsType == SELECT_CELL) { // If moving by cell, also wrap to previous... if (newRowIndex > 0) newRowIndex -= 1; else // ...or the last row newRowIndex = gLastRowIndex; inRow = true; } } else if (newColIndex > gLastColIndex) { // Request is after the last cell in column // Wrap to first cell in column newColIndex = 0; if (gSelectedCellsType == SELECT_CELL) { // If moving by cell, also wrap to next... if (newRowIndex < gLastRowIndex) newRowIndex++; else // ...or the first row newRowIndex = 0; inRow = true; } } } // Get the cell at the new location do { if (!GetCellData(newRowIndex, newColIndex)) { dump("MoveSelection: CELL NOT FOUND\n"); return; } if (inRow) { if (gCellData.startRowIndex == newRowIndex) break; else // Cell spans from a row above, look for the next cell in row newRowIndex += gCellData.actualRowSpan; } else { if (gCellData.startColIndex == newColIndex) break; else // Cell spans from a Col above, look for the next cell in column newColIndex += gCellData.actualColSpan; } } while(true); // Save data for current selection before changing if (gCellDataChanged) // && gDialog.ApplyBeforeMove.checked) { if (!ValidateCellData()) return; gActiveEditor.beginTransaction(); // Apply changes to all selected cells ApplyCellAttributes(); gActiveEditor.endTransaction(); SetCloseButton(); } // Set cell and other data for new selection gCellElement = gCellData.value; // Save globals for new current cell gCurRowIndex = gCellData.startRowIndex; gCurColIndex = gCellData.startColIndex; gCurColSpan = gCellData.actualColSpan; // Copy for new global cell globalCellElement = gCellElement.cloneNode(false); // Change the selection DoCellSelection(); // Scroll page so new selection is visible // Using SELECTION_ANCHOR_REGION makes the upper-left corner of first selected cell // the point to bring into view. try { var selectionController = gActiveEditor.selectionController; selectionController.scrollSelectionIntoView(selectionController.SELECTION_NORMAL, selectionController.SELECTION_ANCHOR_REGION, true); } catch (e) {} // Reinitialize dialog using new cell // if (!gDialog.KeepCurrentData.checked) // Setting this false unchecks all "set attributes" checkboxes gAdvancedEditUsed = false; InitCellPanel(); gAdvancedEditUsed = true; } function DoCellSelection() { // Collapse selection into to the focus cell // so editor uses that as start cell gSelection.collapse(gCellElement, 0); var tagNameObj = { value: "" }; var countObj = { value: 0 }; try { switch (gSelectedCellsType) { case SELECT_CELL: gActiveEditor.selectTableCell(); break case SELECT_ROW: gActiveEditor.selectTableRow(); break; default: gActiveEditor.selectTableColumn(); break; } // Get number of cells selected var tableOrCellElement = gActiveEditor.getSelectedOrParentTableElement(tagNameObj, countObj); } catch (e) {} if (tagNameObj.value == "td") gSelectedCellCount = countObj.value; else gSelectedCellCount = 0; // Currently, we can only allow advanced editing on ONE cell element at a time // else we ignore CSS, JS, and HTML attributes not already in dialog SetElementEnabled(gDialog.AdvancedEditCell, gSelectedCellCount == 1); gDialog.AdvancedEditCell.setAttribute("tooltiptext", gSelectedCellCount > 1 ? GetString("AdvancedEditForCellMsg") : gDialog.AdvancedEditCellToolTipText); } function SetSelectionButtons() { if (gSelectedCellsType == SELECT_ROW) { // Trigger CSS to set images of up and down arrows gDialog.PreviousButton.setAttribute("type","row"); gDialog.NextButton.setAttribute("type","row"); } else { // or images of left and right arrows gDialog.PreviousButton.setAttribute("type","col"); gDialog.NextButton.setAttribute("type","col"); } DisableSelectionButtons((gSelectedCellsType == SELECT_ROW && gRowCount == 1) || (gSelectedCellsType == SELECT_COLUMN && gColCount == 1) || (gRowCount == 1 && gColCount == 1)); } function DisableSelectionButtons( disable ) { gDialog.PreviousButton.setAttribute("disabled", disable ? "true" : "false"); gDialog.NextButton.setAttribute("disabled", disable ? "true" : "false"); } function SwitchToValidatePanel() { if (gDialog.TabBox.selectedTab != gValidateTab) gDialog.TabBox.selectedTab = gValidateTab; } function SetAlign(listID, defaultValue, element, attName) { var value = document.getElementById(listID).value; if (value == defaultValue) { try { gActiveEditor.removeAttributeOrEquivalent(element, attName, true); } catch(e) {} } else { try { gActiveEditor.setAttributeOrEquivalent(element, attName, value, true); } catch(e) {} } } function ValidateTableData() { gValidateTab = gDialog.TableTab; gNewRowCount = Number(ValidateNumber(gDialog.TableRowsInput, null, 1, gMaxRows, null, true, true)); if (gValidationError) return false; gNewColCount = Number(ValidateNumber(gDialog.TableColumnsInput, null, 1, gMaxColumns, null, true, true)); if (gValidationError) return false; // If user is deleting any cells, get confirmation // (This is a global to the dialog and we ask only once per dialog session) if ( !gCanDelete && (gNewRowCount < gRowCount || gNewColCount < gColCount) ) { if (ConfirmWithTitle(GetString("DeleteTableTitle"), GetString("DeleteTableMsg"), GetString("DeleteCells")) ) { gCanDelete = true; } else { SetTextboxFocus(gNewRowCount < gRowCount ? gDialog.TableRowsInput : gDialog.TableColumnsInput); return false; } } ValidateNumber(gDialog.TableWidthInput, gDialog.TableWidthUnits, 1, gMaxTableSize, globalTableElement, "width"); if (gValidationError) return false; if (gUseCSS) { ValidateNumber(gDialog.TableHeightInput, gDialog.TableHeightUnits, 1, gMaxTableSize, globalTableElement, "height"); if (gValidationError) return false; } var border = ValidateNumber(gDialog.BorderWidthInput, null, 0, gMaxPixels, globalTableElement, "border"); // TODO: Deal with "BORDER" without value issue if (gValidationError) return false; ValidateNumber(gDialog.SpacingInput, null, 0, gMaxPixels, globalTableElement, "cellspacing"); if (gValidationError) return false; ValidateNumber(gDialog.PaddingInput, null, 0, gMaxPixels, globalTableElement, "cellpadding"); if (gValidationError) return false; SetAlign("TableAlignList", defHAlign, globalTableElement, "align"); // Color is set on globalCellElement immediately return true; } function ValidateCellData() { gValidateTab = gDialog.CellTab; if (gDialog.CellHeightCheckbox.checked) { ValidateNumber(gDialog.CellHeightInput, gDialog.CellHeightUnits, 1, gMaxTableSize, globalCellElement, "height"); if (gValidationError) return false; } if (gDialog.CellWidthCheckbox.checked) { ValidateNumber(gDialog.CellWidthInput, gDialog.CellWidthUnits, 1, gMaxTableSize, globalCellElement, "width"); if (gValidationError) return false; } if (gDialog.CellHAlignCheckbox.checked) { var hAlign = gDialog.CellHAlignList.value; // Horizontal alignment is complicated by "char" type // We don't change current values if user didn't edit alignment if (!gAlignWasChar) { globalCellElement.removeAttribute(charStr); // Always set "align" attribute, // so the default "left" is effective in a cell // when parent row has align set. globalCellElement.setAttribute("align", hAlign); } } if (gDialog.CellVAlignCheckbox.checked) { // Always set valign (no default in 2nd param) so // the default "middle" is effective in a cell // when parent row has valign set. SetAlign("CellVAlignList", "", globalCellElement, "valign"); } if (gDialog.TextWrapCheckbox.checked) { if (gDialog.TextWrapList.value == "nowrap") try { gActiveEditor.setAttributeOrEquivalent(globalCellElement, "nowrap", "nowrap", true); } catch(e) {} else try { gActiveEditor.removeAttributeOrEquivalent(globalCellElement, "nowrap", true); } catch(e) {} } return true; } function ValidateData() { var result; // Validate current panel first if (gDialog.TabBox.selectedTab == gDialog.TableTab) { result = ValidateTableData(); if (result) result = ValidateCellData(); } else { result = ValidateCellData(); if (result) result = ValidateTableData(); } if(!result) return false; // Set global element for AdvancedEdit if(gDialog.TabBox.selectedTab == gDialog.TableTab) globalElement = globalTableElement; else globalElement = globalCellElement; return true; } function ChangeCellTextbox(textboxID) { // Filter input for just integers forceInteger(textboxID); if (gDialog.TabBox.selectedTab == gDialog.CellTab) gCellDataChanged = true; } // Call this when a textbox or menulist is changed // so the checkbox is automatically set function SetCheckbox(checkboxID) { if (checkboxID && checkboxID.length > 0) { // Set associated checkbox document.getElementById(checkboxID).checked = true; } gCellDataChanged = true; } function ChangeIntTextbox(textboxID, checkboxID) { // Filter input for just integers forceInteger(textboxID); // Set associated checkbox SetCheckbox(checkboxID); } function CloneAttribute(destElement, srcElement, attr) { var value = srcElement.getAttribute(attr); // Use editor methods since we are always // modifying a table in the document and // we need transaction system for undo try { if (!value || value.length == 0) gActiveEditor.removeAttributeOrEquivalent(destElement, attr, false); else gActiveEditor.setAttributeOrEquivalent(destElement, attr, value, false); } catch(e) {} } function ApplyTableAttributes() { var newAlign = gDialog.TableCaptionList.value; if (!newAlign) newAlign = ""; if (gTableCaptionElement) { // Get current alignment var align = GetHTMLOrCSSStyleValue(gTableCaptionElement, "align", "caption-side").toLowerCase(); // This is the default if (!align) align = "top"; if (newAlign == "") { // Remove existing caption try { gActiveEditor.deleteNode(gTableCaptionElement); } catch(e) {} gTableCaptionElement = null; } else if(newAlign != align) { try { if (newAlign == "top") // This is default, so don't explicitly set it gActiveEditor.removeAttributeOrEquivalent(gTableCaptionElement, "align", false); else gActiveEditor.setAttributeOrEquivalent(gTableCaptionElement, "align", newAlign, false); } catch(e) {} } } else if (newAlign != "") { // Create and insert a caption: try { gTableCaptionElement = gActiveEditor.createElementWithDefaults("caption"); } catch (e) {} if (gTableCaptionElement) { if (newAlign != "top") gTableCaptionElement.setAttribute("align", newAlign); // Insert it into the table - caption is always inserted as first child try { gActiveEditor.insertNode(gTableCaptionElement, gTableElement, 0); } catch(e) {} // Put selecton back where it was ChangeSelection(RESET_SELECTION); } } var countDelta; var foundCell; var i; if (gNewRowCount != gRowCount) { countDelta = gNewRowCount - gRowCount; if (gNewRowCount > gRowCount) { // Append new rows // Find first cell in last row if(GetCellData(gLastRowIndex, 0)) { try { // Move selection to the last cell gSelection.collapse(gCellData.value,0); // Insert new rows after it gActiveEditor.insertTableRow(countDelta, true); gRowCount = gNewRowCount; gLastRowIndex = gRowCount - 1; // Put selecton back where it was ChangeSelection(RESET_SELECTION); } catch(ex) { dump("FAILED TO FIND FIRST CELL IN LAST ROW\n"); } } } else { // Delete rows if (gCanDelete) { // Find first cell starting in first row we delete var firstDeleteRow = gRowCount + countDelta; foundCell = false; for ( i = 0; i <= gLastColIndex; i++) { if (!GetCellData(firstDeleteRow, i)) break; // We failed to find a cell if (gCellData.startRowIndex == firstDeleteRow) { foundCell = true; break; } }; if (foundCell) { try { // Move selection to the cell we found gSelection.collapse(gCellData.value, 0); gActiveEditor.deleteTableRow(-countDelta); gRowCount = gNewRowCount; gLastRowIndex = gRowCount - 1; if (gCurRowIndex > gLastRowIndex) // We are deleting our selection // move it to start of table ChangeSelectionToFirstCell() else // Put selecton back where it was ChangeSelection(RESET_SELECTION); } catch(ex) { dump("FAILED TO FIND FIRST CELL IN LAST ROW\n"); } } } } } if (gNewColCount != gColCount) { countDelta = gNewColCount - gColCount; if (gNewColCount > gColCount) { // Append new columns // Find last cell in first column if(GetCellData(0, gLastColIndex)) { try { // Move selection to the last cell gSelection.collapse(gCellData.value,0); gActiveEditor.insertTableColumn(countDelta, true); gColCount = gNewColCount; gLastColIndex = gColCount-1; // Restore selection ChangeSelection(RESET_SELECTION); } catch(ex) { dump("FAILED TO FIND FIRST CELL IN LAST COLUMN\n"); } } } else { // Delete columns if (gCanDelete) { var firstDeleteCol = gColCount + countDelta; foundCell = false; for ( i = 0; i <= gLastRowIndex; i++) { // Find first cell starting in first column we delete if (!GetCellData(i, firstDeleteCol)) break; // We failed to find a cell if (gCellData.startColIndex == firstDeleteCol) { foundCell = true; break; } }; if (foundCell) { try { // Move selection to the cell we found gSelection.collapse(gCellData.value, 0); gActiveEditor.deleteTableColumn(-countDelta); gColCount = gNewColCount; gLastColIndex = gColCount-1; if (gCurColIndex > gLastColIndex) ChangeSelectionToFirstCell() else ChangeSelection(RESET_SELECTION); } catch(ex) { dump("FAILED TO FIND FIRST CELL IN LAST ROW\n"); } } } } } // Clone all remaining attributes to pick up // anything changed by Advanced Edit Dialog try { gActiveEditor.cloneAttributes(gTableElement, globalTableElement); } catch(e) {} } function ApplyCellAttributes() { var rangeObj = { value: null }; var selectedCell; try { selectedCell = gActiveEditor.getFirstSelectedCell(rangeObj); } catch(e) {} if (!selectedCell) return; if (gSelectedCellCount == 1) { // When only one cell is selected, simply clone entire element, // thus CSS and JS from Advanced edit is copied try { gActiveEditor.cloneAttributes(selectedCell, globalCellElement); } catch(e) {} if (gDialog.CellStyleCheckbox.checked) { var currentStyleIndex = (selectedCell.nodeName.toLowerCase() == "th") ? 1 : 0; if (gDialog.CellStyleList.selectedIndex != currentStyleIndex) { // Switch cell types // (replaces with new cell and copies attributes and contents) try { selectedCell = gActiveEditor.switchTableCellHeaderType(selectedCell); } catch(e) {} } } } else { // Apply changes to all selected cells //XXX THIS DOESN'T COPY ADVANCED EDIT CHANGES! try { while (selectedCell) { ApplyAttributesToOneCell(selectedCell); selectedCell = gActiveEditor.getNextSelectedCell(rangeObj); } } catch(e) {} } gCellDataChanged = false; } function ApplyAttributesToOneCell(destElement) { if (gDialog.CellHeightCheckbox.checked) CloneAttribute(destElement, globalCellElement, "height"); if (gDialog.CellWidthCheckbox.checked) CloneAttribute(destElement, globalCellElement, "width"); if (gDialog.CellHAlignCheckbox.checked) { CloneAttribute(destElement, globalCellElement, "align"); CloneAttribute(destElement, globalCellElement, charStr); } if (gDialog.CellVAlignCheckbox.checked) CloneAttribute(destElement, globalCellElement, "valign"); if (gDialog.TextWrapCheckbox.checked) CloneAttribute(destElement, globalCellElement, "nowrap"); if (gDialog.CellStyleCheckbox.checked) { var newStyleIndex = gDialog.CellStyleList.selectedIndex; var currentStyleIndex = (destElement.nodeName.toLowerCase() == "th") ? 1 : 0; if (newStyleIndex != currentStyleIndex) { // Switch cell types // (replaces with new cell and copies attributes and contents) try { destElement = gActiveEditor.switchTableCellHeaderType(destElement); } catch(e) {} } } if (gDialog.CellColorCheckbox.checked) CloneAttribute(destElement, globalCellElement, "bgcolor"); } function SetCloseButton() { // Change text on "Cancel" button after Apply is used if (!gApplyUsed) { document.documentElement.setAttribute("buttonlabelcancel", document.documentElement.getAttribute("buttonlabelclose")); gApplyUsed = true; } } function Apply() { if (ValidateData()) { gActiveEditor.beginTransaction(); ApplyTableAttributes(); // We may have just a table, so check for cell element if (globalCellElement) ApplyCellAttributes(); gActiveEditor.endTransaction(); SetCloseButton(); return true; } return false; } function doHelpButton() { openHelp("table_properties"); } function onAccept() { // Do same as Apply and close window if ValidateData succeeded var retVal = Apply(); if (retVal) SaveWindowLocation(); return retVal; }