/* * The contents of this file are subject to the Netscape 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/NPL/ * * 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 Netscape are * Copyright (C) 1998-1999 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * Pete Collins * Brian King * Ben Goodger */ var insertNew = true; var insertNewIMap = true; var wasEnableAll = false; var oldSourceInt = 0; var imageElement; var imageMap = 0; var canRemoveImageMap = false; var imageMapDisabled = false; // dialog initialization code function Startup() { if (!InitEditorShell()) return; doSetOKCancel(onOK, null); // Create dialog object to store controls for easy access dialog = new Object; dialog.srcInput = document.getElementById( "srcInput" ); dialog.altTextInput = document.getElementById( "altTextInput" ); dialog.MoreFewerButton = document.getElementById( "MoreFewerButton" ); dialog.AdvancedEditButton = document.getElementById( "AdvancedEditButton" ); dialog.AdvancedEditButton2 = document.getElementById( "AdvancedEditButton2" ); dialog.MoreSection = document.getElementById( "MoreSection" ); dialog.customsizeRadio = document.getElementById( "customsizeRadio" ); dialog.originalsizeRadio = document.getElementById( "originalsizeRadio" ); dialog.constrainCheckbox = document.getElementById( "constrainCheckbox" ); dialog.widthInput = document.getElementById( "widthInput" ); dialog.heightInput = document.getElementById( "heightInput" ); dialog.widthUnitsMenulist = document.getElementById( "widthUnitsMenulist" ); dialog.heightUnitsMenulist = document.getElementById( "heightUnitsMenulist" ); dialog.imagelrInput = document.getElementById( "imageleftrightInput" ); dialog.imagetbInput = document.getElementById( "imagetopbottomInput" ); dialog.border = document.getElementById( "border" ); dialog.alignTypeSelect = document.getElementById( "alignTypeSelect" ); dialog.editImageMap = document.getElementById( "editImageMap" ); dialog.removeImageMap = document.getElementById( "removeImageMap" ); dialog.doConstrain = false; dialog.isCustomSize = false; // Get a single selected image element var tagName = "img" imageElement = editorShell.GetSelectedElement(tagName); if (imageElement) { // We found an element and don't need to insert one insertNew = false; } else { insertNew = true; // We don't have an element selected, // so create one with default attributes imageElement = editorShell.CreateElementWithDefaults(tagName); if( !imageElement ) { dump("Failed to get selected element or create a new one!\n"); window.close(); } } // Make a copy to use for AdvancedEdit globalElement = imageElement.cloneNode(false); // Get image map for image var usemap = globalElement.getAttribute("usemap"); if (usemap) { mapname = usemap.substring(1, usemap.length); mapCollection = editorShell.editorDocument.getElementsByName(mapname); if (mapCollection[0] != null) { imageMap = mapCollection[0]; canRemoveImageMap = true; insertNewIMap = false; dump(imageMap.childNodes.length+"\n"); } else { insertNewIMap = true; globalMap = null; } } else { insertNewIMap = true; globalMap = null; } // Set SeeMore bool to the OPPOSITE of the current state, // which is automatically saved by using the 'persist="more"' // attribute on the MoreFewerButton button // onMoreFewerImage will toggle the state and redraw the dialog SeeMore = (dialog.MoreFewerButton.getAttribute("more") != "1"); // Initialize widgets with image attributes in the case where the entire dialog isn't visible if ( SeeMore ) // this is actually in the opposite state until onMoreFewerImage is called below InitDialog(); onMoreFewerImage(); // this call will initialize all widgets if entire dialog is visible dialog.srcInput.focus(); } // Set dialog widgets with attribute data // We get them from globalElement copy so this can be used // by AdvancedEdit(), which is shared by all property dialogs function InitDialog() { // Set the controls to the image's attributes str = globalElement.getAttribute("src"); if (str) dialog.srcInput.value = str; str = globalElement.getAttribute("alt"); if (str) dialog.altTextInput.value = str; // Check for image map if ( SeeMore ) { // setup the height and width widgets dialog.widthInput.value = InitPixelOrPercentMenulist(globalElement, imageElement, "width", "widthUnitsMenulist"); dialog.heightInput.value = InitPixelOrPercentMenulist(globalElement, imageElement, "height", "heightUnitsMenulist"); // TODO: We need to get the actual image dimensions. // If different from attribute dimensions, then "custom" is checked. // For now, always check custom, so we don't trash existing values if ( dialog.widthInput.value.length && dialog.heightInput.value.length && dialog.widthInput.value != "0" && dialog.heightInput.value != "0") { dialog.isCustomSize = true; dialog.customsizeRadio.checked = true; } else { dialog.isCustomSize = false; dialog.originalsizeRadio.checked = true; } // set spacing editfields dialog.imagelrInput.value = globalElement.getAttribute("hspace"); dialog.imagetbInput.value = globalElement.getAttribute("vspace"); dialog.border.value = globalElement.getAttribute("border"); // Get alignment setting var align = globalElement.getAttribute("align"); if (align) { align = align.toLowerCase(); } switch ( align ) { case "top": dialog.alignTypeSelect.selectedIndex = 0; break; case "center": dialog.alignTypeSelect.selectedIndex = 1; break; case "right": dialog.alignTypeSelect.selectedIndex = 3; break; case "left": dialog.alignTypeSelect.selectedIndex = 4; break; default: // Default or "bottom" dialog.alignTypeSelect.selectedIndex = 2; break; } } // we want to force an update so initialize "wasEnableAll" to be the opposite of what the actual state is wasEnableAll = !IsValidImage(dialog.srcInput.value); doOverallEnabling(); } function chooseFile() { // Get a local file, converted into URL format fileName = GetLocalFileURL("img"); if (fileName && fileName != "") { dialog.srcInput.value = fileName; doOverallEnabling(); } // Put focus into the input field dialog.srcInput.focus(); } function SetGlobalElementToCurrentDialogSettings() { // src var str = dialog.srcInput.value.trimString(); globalElement.setAttribute("src", str); // alt str = dialog.altTextInput.value.trimString(); globalElement.setAttribute("alt", str); var alignment; //Note that the attributes "left" and "right" are opposite // of what we use in the UI, which describes where the TEXT wraps, // not the image location (which is what the HTML describes) switch ( dialog.alignTypeSelect.selectedIndex ) { case 0: alignment = "top"; break; case 1: alignment = "center"; break; case 3: alignment = "right"; break; case 4: alignment = "left"; break; default: // Default or "bottom" (2) alignment = ""; break; } dump("alignment ="+alignment+"\n"); if ( alignment == "" ) globalElement.removeAttribute( "align" ); else globalElement.setAttribute( "align", alignment ); if ( dialog.imagelrInput.value.length > 0 ) globalElement.setAttribute("hspace", dialog.imagelrInput.value); else globalElement.removeAttribute("hspace"); if ( dialog.imagetbInput.value.length > 0 ) globalElement.setAttribute("vspace", dialog.imagetbInput.value); else globalElement.removeAttribute("vspace"); if ( dialog.border.value.length > 0 ) globalElement.setAttribute("border", dialog.border.value); else globalElement.removeAttribute("border"); // width str = dialog.widthInput.value; if (dialog.widthUnitsMenulist.selectedIndex == 1) str = str + "%"; globalElement.setAttribute("width", str); // height str = dialog.heightInput.value; if (dialog.heightUnitsMenulist.selectedIndex == 1) str = str + "%"; globalElement.setAttribute("height", str); } function onMoreFewerImage() { if (SeeMore) { dialog.isCustomSize = dialog.customsizeRadio.checked; dialog.doConstrain = dialog.constrainCheckbox.checked; SetGlobalElementToCurrentDialogSettings(); //dialog.MoreSection.setAttribute("style","display: none"); dialog.MoreSection.setAttribute("collapsed","true"); window.sizeToContent(); dialog.MoreFewerButton.setAttribute("more","0"); dialog.MoreFewerButton.setAttribute("value",GetString("MoreProperties")); SeeMore = false; // Show the "Advanced Edit" button on same line as "More Properties" dialog.AdvancedEditButton.removeAttribute("hidden"); dialog.AdvancedEditButton2.setAttribute("hidden","true"); } else { //dialog.MoreSection.setAttribute("style","display: inherit"); dialog.MoreSection.removeAttribute("collapsed"); // Hide the "Advanced Edit" next to "More..." Use button at bottom right of dialog dialog.AdvancedEditButton.setAttribute("style","display: none"); window.sizeToContent(); dialog.MoreFewerButton.setAttribute("more","1"); dialog.MoreFewerButton.setAttribute("value",GetString("FewerProperties")); SeeMore = true; // Show the "Advanced Edit" button at bottom dialog.AdvancedEditButton.setAttribute("hidden","true"); dialog.AdvancedEditButton2.removeAttribute("hidden"); InitDialog(); //TODO: We won't need to do this when we convert to using "collapsed" if (dialog.isCustomSize) { dialog.customsizeRadio.checked = true; dialog.originalsizeRadio.checked = false; } else { dialog.customsizeRadio.checked = false; dialog.originalsizeRadio.checked = true; } if (dialog.doConstrain) dialog.constrainCheckbox.checked = true; } } function doDimensionEnabling( doEnable ) { SetElementEnabledById( "originalsizeRadio", doEnable ); SetElementEnabledById( "customsizeRadio", doEnable); // Enabled only if "Custom" is checked var enable = (doEnable && dialog.customsizeRadio.checked); if ( !dialog.customsizeRadio.checked && !dialog.originalsizeRadio.checked) dump("BUG! neither radio button is checked!!!! \n"); SetElementEnabledById( "widthInput", enable ); SetElementEnabledById( "widthLabel", enable); SetElementEnabledById( "widthUnitsMenulist", enable ); SetElementEnabledById( "heightInput", enable ); SetElementEnabledById( "heightLabel", enable ); SetElementEnabledById( "heightUnitsMenulist", enable ); var constrainEnable = enable && ( dialog.widthUnitsMenulist.selectedIndex == 0 ) && ( dialog.heightUnitsMenulist.selectedIndex == 0 ); SetElementEnabledById( "constrainCheckbox", constrainEnable ); } function doOverallEnabling() { var canEnableAll = IsValidImage(dialog.srcInput.value); if ( wasEnableAll == canEnableAll ) return; wasEnableAll = canEnableAll; SetElementEnabledById("ok", canEnableAll ); SetElementEnabledById( "altTextLabel", canEnableAll ); // Do widgets for sizing SetElementEnabledById( "dimensionsLabel", canEnableAll ); doDimensionEnabling( canEnableAll ); SetElementEnabledById("alignLabel", canEnableAll ); SetElementEnabledById("alignTypeSelect", canEnableAll ); // spacing Box SetElementEnabledById( "spacingLabel", canEnableAll ); SetElementEnabledById( "imageleftrightInput", canEnableAll ); SetElementEnabledById( "leftrightLabel", canEnableAll ); SetElementEnabledById( "leftrighttypeLabel", canEnableAll ); SetElementEnabledById( "imagetopbottomInput", canEnableAll ); SetElementEnabledById( "topbottomLabel", canEnableAll ); SetElementEnabledById( "topbottomtypeLabel", canEnableAll ); SetElementEnabledById( "border", canEnableAll ); SetElementEnabledById( "borderLabel", canEnableAll ); SetElementEnabledById( "bordertypeLabel", canEnableAll ); // This shouldn't find button, but it does! SetElementEnabledById( "AdvancedEditButton", canEnableAll ); SetElementEnabledById( "AdvancedEditButton2", canEnableAll ); SetElementEnabledById( "imagemapLabel", canEnableAll ); SetElementEnabledById( "editImageMap", canEnableAll ); SetElementEnabledById( "removeImageMap", canEnableAll && canRemoveImageMap); } // constrainProportions contribution by pete@postpagan.com function constrainProportions( srcID, destID ) { srcElement = document.getElementById ( srcID ); if ( !srcElement ) return; forceInteger( srcID ); // now find out if we should be constraining or not var constrainChecked = (dialog.constrainCheckbox.checked); constrainChecked = constrainChecked && !dialog.constrainCheckbox.disabled; if ( !constrainChecked ) return; destElement = document.getElementById( destID ); if ( !destElement ) return; // set new value in the other edit field // src / dest ratio mantained // newDest = (newSrc * oldDest / oldSrc) if ( oldSourceInt == 0 ) destElement.value = srcElement.value; else destElement.value = Math.round( srcElement.value * destElement.value / oldSourceInt ); oldSourceInt = srcElement.value; } function editImageMap() { // Make a copy to use for image map editor if (insertNewIMap) { imageMap = editorShell.CreateElementWithDefaults("map"); globalMap = imageMap.cloneNode(true); } else globalMap = imageMap; window.openDialog("chrome://editor/content/EdImageMap.xul", "_blank", "chrome,close,titlebar,modal", globalElement, globalMap); } function removeImageMap() { globalElement.removeAttribute("usemap"); if (imageMap){ canRemoveImageMap = false; SetElementEnabledByID( "removeImageMap", false); editorShell.DeleteElement(imageMap); insertNewIMap = true; globalMap = null; } } // Get data from widgets, validate, and set for the global element // accessible to AdvancedEdit() [in EdDialogCommon.js] function ValidateData() { if ( !IsValidImage(dialog.srcInput.value )) { ShowInputErrorMessage(GetString("MissingImageError")); return false; } //TODO: WE NEED TO DO SOME URL VALIDATION HERE, E.G.: // We must convert to "file:///" or "http://" format else image doesn't load! var src = dialog.srcInput.value.trimString(); globalElement.setAttribute("src", src); // TODO: Should we confirm with user if no alt tag? Or just set to empty string? var alt = dialog.altTextInput.value.trimString(); globalElement.setAttribute("alt", alt); //TODO: WE SHOULD ALWAYS SET WIDTH AND HEIGHT FOR FASTER IMAGE LAYOUT // IF USER DOESN'T SET IT, WE NEED TO GET VALUE FROM ORIGINAL IMAGE var width = ""; var height = ""; var isPercentWidth, isPercentHeight; var maxLimitWidth, maxLimitHeight; if ( SeeMore ) { dialog.isCustomSize = dialog.customsizeRadio.checked; isPercentWidth = (dialog.widthUnitsMenulist.selectedIndex == 1); isPercentHeight = (dialog.heightUnitsMenulist.selectedIndex == 1); } else /* can't SeeMore */ { var tailindex; width = globalElement.getAttribute( "width" ); tailindex = width.lastIndexOf("%"); isPercentWidth = ( tailindex > 0 ); if ( isPercentWidth ) width = width.substring(0, tailindex); height = globalElement.getAttribute( "height" ); tailindex = height.lastIndexOf("%"); isPercentHeight = ( tailindex > 0 ); if ( isPercentHeight ) height = height.substring(0, tailindex); } if ( SeeMore && dialog.originalsizeRadio.checked ) { // original size: don't do anything right now } else if ( (SeeMore && dialog.customsizeRadio.checked) || dialog.isCustomSize ) { maxLimitWidth = isPercentWidth ? 100 : maxPixels; // Defined in EdDialogCommon.js width = ValidateNumberString(dialog.widthInput.value, 1, maxLimitWidth); if (width == "") { if ( !SeeMore ) onMoreFewerImage(); dialog.widthInput.focus(); return false; } if (isPercentWidth) width = width + "%"; maxLimitHeight = isPercentHeight ? 100 : maxPixels; // Defined in EdDialogCommon.js height = ValidateNumberString(dialog.heightInput.value, 1, maxLimitHeight); if (height == "") { if ( !SeeMore ) onMoreFewerImage(); dialog.heightInput.focus(); return false; } if (isPercentHeight) height = height + "%"; } if ( !dialog.isCustomSize ) { // for now (until we can get the actual image dimensions), clear the height/width attributes if not set globalElement.removeAttribute( "width" ); globalElement.removeAttribute( "height" ); } else { if (width.length > 0) globalElement.setAttribute("width", width); if (height.length > 0) globalElement.setAttribute("height", height); } // spacing attributes // All of these should use ValidateNumberString() to // ensure value is within acceptable range var amount; if ( SeeMore ) { dump("SeeMore spacing attribs\n"); if ( dialog.imagelrInput.value.length > 0 ) { amount = ValidateNumberString(dialog.imagelrInput.value, 0, maxPixels); if (amount == "") return false; globalElement.setAttribute( "hspace", amount ); } else globalElement.removeAttribute( "hspace" ); if ( dialog.imagetbInput.value.length > 0 ) { var vspace = ValidateNumberString(dialog.imagetbInput.value, 0, maxPixels); if (vspace == "") return false; globalElement.setAttribute( "vspace", vspace ); } else globalElement.removeAttribute( "vspace" ); // note this is deprecated and should be converted to stylesheets if ( dialog.border.value.length > 0 ) { var border = ValidateNumberString(dialog.border.value, 0, maxPixels); if (border == "") return false; globalElement.setAttribute( "border", border ); } else globalElement.removeAttribute( "border" ); // Default or setting "bottom" means don't set the attribute // Note that the attributes "left" and "right" are opposite // of what we use in the UI, which describes where the TEXT wraps, // not the image location (which is what the HTML describes) var align = ""; switch ( dialog.alignTypeSelect.selectedIndex ) { case 0: align = "top"; break; case 1: align = "center"; break; case 3: align = "right"; break; case 4: align = "left"; break; } if (align == "") globalElement.removeAttribute( "align" ); else globalElement.setAttribute( "align", align ); } return true; } function onOK() { // handle insertion of new image if (ValidateData()) { // Assign to map if there is one if ( globalMap ) { mapName = globalMap.getAttribute("name"); dump("mapName = "+mapName+"\n"); if (mapName != "") { globalElement.setAttribute("usemap", ("#"+mapName)); if (globalElement.getAttribute("border") == "") globalElement.setAttribute("border", 0); } // Copy or insert image map imageMap = globalMap.cloneNode(true); if (insertNewIMap) { try { editorShell.editorDocument.body.appendChild(imageMap); //editorShell.InsertElementAtSelection(imageMap, false); } catch (e) { dump("Exception occured in InsertElementAtSelection\n"); } } } // All values are valid - copy to actual element in doc or // element created to insert editorShell.CloneAttributes(imageElement, globalElement); if (insertNew) { try { // 'true' means delete the selection before inserting editorShell.InsertElementAtSelection(imageElement, true); } catch (e) { dump("Exception occured in InsertElementAtSelection\n"); } } // un-comment to see that inserting image maps does not work! /*test = editorShell.CreateElementWithDefaults("map"); test.setAttribute("name", "testing"); testArea = editorShell.CreateElementWithDefaults("area"); testArea.setAttribute("shape", "circle"); testArea.setAttribute("coords", "86,102,52"); testArea.setAttribute("href", "test"); test.appendChild(testArea); editorShell.InsertElementAtSelection(test, false);*/ return true; } return false; }