622 lines
18 KiB
JavaScript
622 lines
18 KiB
JavaScript
/*
|
|
* 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 SeeMore = true;
|
|
var wasEnableAll = false;
|
|
var oldSourceInt = 0;
|
|
var imageElement;
|
|
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.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.widthUnitsSelect = document.getElementById( "widthUnitsSelect" );
|
|
dialog.heightUnitsSelect = document.getElementById( "heightUnitsSelect" );
|
|
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;
|
|
|
|
// Another version of button just for this dialog -- on same line as "More Properties"
|
|
dialog.AdvancedEditButton2 = document.getElementById( "AdvancedEditButton2" );
|
|
|
|
// 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);
|
|
|
|
// Set SeeMore bool to the OPPOSITE of the current state,
|
|
// which is automatically saved by using the 'persist="more"'
|
|
// attribute on the MoreFewerButton button
|
|
// onMoreFewer 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 onMoreFewer is called below
|
|
InitDialog();
|
|
|
|
onMoreFewer(); // 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;
|
|
|
|
if ( SeeMore )
|
|
{
|
|
// setup the height and width widgets
|
|
dialog.widthInput.value = InitPixelOrPercentCombobox(globalElement, "width", "widthUnitsSelect");
|
|
dialog.heightInput.value = InitPixelOrPercentCombobox(globalElement, "height", "heightUnitsSelect");
|
|
|
|
// 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.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;
|
|
}
|
|
}
|
|
|
|
imageTypeExtension = checkForImage();
|
|
// we want to force an update so initialize "wasEnableAll" to be the opposite of what the actual state is
|
|
wasEnableAll = !imageTypeExtension;
|
|
doOverallEnabling();
|
|
}
|
|
|
|
function chooseFile()
|
|
{
|
|
// Get a local file, converted into URL format
|
|
|
|
fileName = editorShell.GetLocalFileURL(window, "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.widthUnitsSelect.selectedIndex == 1)
|
|
str = str + "%";
|
|
globalElement.setAttribute("width", str);
|
|
|
|
// height
|
|
str = dialog.heightInput.value;
|
|
if (dialog.heightUnitsSelect.selectedIndex == 1)
|
|
str = str + "%";
|
|
globalElement.setAttribute("height", str);
|
|
}
|
|
|
|
function onMoreFewer()
|
|
{
|
|
if (SeeMore)
|
|
{
|
|
dialog.isCustomSize = dialog.customsizeRadio.checked;
|
|
dialog.doConstrain = dialog.constrainCheckbox.checked;
|
|
SetGlobalElementToCurrentDialogSettings();
|
|
|
|
dialog.MoreSection.setAttribute("style","display: none");
|
|
// Show the "Advanced Edit" button on same line as "More Properties"
|
|
dialog.AdvancedEditButton2.setAttribute("style","display: inherit");
|
|
window.sizeToContent();
|
|
dialog.MoreFewerButton.setAttribute("more","0");
|
|
dialog.MoreFewerButton.setAttribute("value",GetString("MoreProperties"));
|
|
SeeMore = false;
|
|
}
|
|
else
|
|
{
|
|
dialog.MoreSection.setAttribute("style","display: inherit");
|
|
// Hide the "Advanced Edit" next to "More..." Use button at bottom right of dialog
|
|
dialog.AdvancedEditButton2.setAttribute("style","display: none");
|
|
window.sizeToContent();
|
|
|
|
dialog.MoreFewerButton.setAttribute("more","1");
|
|
dialog.MoreFewerButton.setAttribute("value",GetString("FewerProperties"));
|
|
SeeMore = true;
|
|
|
|
InitDialog();
|
|
|
|
if (dialog.isCustomSize)
|
|
dialog.customsizeRadio.checked = true;
|
|
else
|
|
dialog.originalsizeRadio.checked = true;
|
|
|
|
if (dialog.doConstrain)
|
|
dialog.constrainCheckbox.checked = true;
|
|
}
|
|
}
|
|
|
|
function doDimensionEnabling( doEnable )
|
|
{
|
|
// Enabled only if "Custom" is checked
|
|
var enable = (doEnable && dialog.customsizeRadio.checked);
|
|
|
|
SetElementEnabledByID( "widthInput", enable );
|
|
SetElementEnabledByID( "widthLabel", enable);
|
|
SetElementEnabledByID( "widthUnitsSelect", enable );
|
|
|
|
SetElementEnabledByID( "heightInput", enable );
|
|
SetElementEnabledByID( "heightLabel", enable );
|
|
SetElementEnabledByID( "heightUnitsSelect", enable );
|
|
|
|
|
|
SetElementEnabledByID( "constrainCheckbox", enable );
|
|
SetElementEnabledByID( "constrainLabel", enable );
|
|
}
|
|
|
|
function doOverallEnabling()
|
|
{
|
|
var imageTypeExtension = checkForImage();
|
|
var canEnableAll = imageTypeExtension != 0;
|
|
if ( wasEnableAll == canEnableAll )
|
|
return;
|
|
|
|
wasEnableAll = canEnableAll;
|
|
|
|
SetElementEnabledByID("ok", canEnableAll );
|
|
SetElementEnabledByID( "altTextLabel", canEnableAll );
|
|
|
|
// Do widgets for sizing
|
|
SetElementEnabledByID( "originalsizeLabel", canEnableAll );
|
|
SetElementEnabledByID( "customsizeLabel", canEnableAll );
|
|
SetElementEnabledByID( "dimensionsLabel", canEnableAll );
|
|
doDimensionEnabling( canEnableAll );
|
|
|
|
SetElementEnabledByID("alignLabel", canEnableAll );
|
|
SetElementEnabledByID("alignTypeSelect", canEnableAll );
|
|
|
|
// spacing fieldset
|
|
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( "AdvancedEditButton2", canEnableAll );
|
|
SetElementEnabledByID( "AdvancedEditButton3", canEnableAll );
|
|
|
|
SetElementEnabledByID( "editImageMap", canEnableAll );
|
|
// TODO: ADD APPROPRIATE DISABLING BASED ON EXISTENCE OF IMAGE MAP
|
|
SetElementEnabledByID( "removeImageMap", canEnableAll && canRemoveImageMap);
|
|
}
|
|
|
|
// an API to validate and image by sniffing out the extension
|
|
/* assumes that the element id is "srcInput" */
|
|
/* returns lower-case extension or 0 */
|
|
function checkForImage()
|
|
{
|
|
image = dialog.srcInput.value.trimString();
|
|
if ( !image )
|
|
return 0;
|
|
|
|
/* look for an extension */
|
|
var tailindex = image.lastIndexOf(".");
|
|
if ( tailindex == 0 || tailindex == -1 ) /* -1 is not found */
|
|
return 0;
|
|
|
|
/* move past period, get the substring from the first character after the '.' to the last character (length) */
|
|
tailindex = tailindex + 1;
|
|
var type = image.substring(tailindex,image.length);
|
|
|
|
/* convert extension to lower case */
|
|
if (type)
|
|
type = type.toLowerCase();
|
|
|
|
// TODO: Will we convert .BMPs to a web format?
|
|
switch( type ) {
|
|
case "gif":
|
|
case "jpg":
|
|
case "jpeg":
|
|
case "png":
|
|
return type;
|
|
break;
|
|
default :
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
// constrainProportions contribution by pete@postpagan.com
|
|
// needs to handle pixels/percent
|
|
|
|
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);
|
|
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()
|
|
{
|
|
dump("editImageMap -- WRITE ME!\n");
|
|
}
|
|
|
|
function removeImageMap()
|
|
{
|
|
dump("removeImageMap -- WRITE ME!\n");
|
|
}
|
|
|
|
// Get data from widgets, validate, and set for the global element
|
|
// accessible to AdvancedEdit() [in EdDialogCommon.js]
|
|
function ValidateData()
|
|
{
|
|
var imageTypeExtension = checkForImage();
|
|
if ( !imageTypeExtension ) {
|
|
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.widthUnitsSelect.selectedIndex == 1);
|
|
isPercentHeight = (dialog.heightUnitsSelect.selectedIndex == 1);
|
|
width = dialog.widthInput.value;
|
|
height = dialog.heightInput.value;
|
|
}
|
|
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 ( dialog.isCustomSize )
|
|
{
|
|
maxLimitWidth = isPercentWidth ? 100 : maxPixels; // Defined in EdDialogCommon.js
|
|
width = ValidateNumberString(width, 1, maxLimitWidth);
|
|
if (width == "") {
|
|
if ( !SeeMore )
|
|
onMoreFewer();
|
|
dialog.widthInput.focus();
|
|
return false;
|
|
}
|
|
if (isPercentWidth)
|
|
width = width + "%";
|
|
|
|
maxLimitHeight = isPercentHeight ? 100 : maxPixels; // Defined in EdDialogCommon.js
|
|
height = ValidateNumberString(height, 1, maxLimitHeight);
|
|
if (height == "") {
|
|
if ( !SeeMore )
|
|
onMoreFewer();
|
|
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 )
|
|
{
|
|
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())
|
|
{
|
|
// 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");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|