Added support to use relative URLs in link and image dialogs and let user convert to/from absolute URLs, b=72583, r=brade,akkana, sr=kin
git-svn-id: svn://10.0.0.236/trunk@103003 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
6f4b44bcf4
commit
8667c2b02f
@ -62,6 +62,7 @@ var backgroundStr = "background";
|
||||
var colorStyle = "color: ";
|
||||
var backColorStyle = "background-color: ";
|
||||
var backImageStyle = "; background-image: url(";
|
||||
var gHaveDocumentUrl = false;
|
||||
|
||||
// dialog initialization code
|
||||
function Startup()
|
||||
@ -110,6 +111,9 @@ function Startup()
|
||||
defaultBackgroundColor= browserColors.BackgroundColor;
|
||||
}
|
||||
|
||||
// We only need to test for this once per dialog load
|
||||
gHaveDocumentUrl = GetDocumentBaseUrl();
|
||||
|
||||
InitDialog();
|
||||
|
||||
if (dialog.DefaultColorsRadio.checked)
|
||||
@ -124,12 +128,14 @@ function InitDialog()
|
||||
{
|
||||
// Get image from document
|
||||
backgroundImage = globalElement.getAttribute(backgroundStr);
|
||||
if (backgroundImage.length > 0)
|
||||
if (backgroundImage.length)
|
||||
{
|
||||
dialog.BackgroundImageInput.value = backgroundImage;
|
||||
dialog.ColorPreview.setAttribute(styleStr, backImageStyle+backgroundImage+");");
|
||||
}
|
||||
|
||||
SetRelativeCheckbox();
|
||||
|
||||
customTextColor = globalElement.getAttribute(textStr);
|
||||
customLinkColor = globalElement.getAttribute(linkStr);
|
||||
customActiveColor = globalElement.getAttribute(alinkStr);
|
||||
@ -324,7 +330,14 @@ function chooseFile()
|
||||
var fileName = GetLocalFileURL("img");
|
||||
if (fileName)
|
||||
{
|
||||
// Always try to relativize local file URLs
|
||||
if (gHaveDocumentUrl)
|
||||
fileName = MakeRelativeUrl(fileName);
|
||||
|
||||
dialog.BackgroundImageInput.value = fileName;
|
||||
|
||||
SetRelativeCheckbox();
|
||||
|
||||
ValidateAndPreviewImage(true);
|
||||
}
|
||||
SetTextboxFocus(dialog.BackgroundImageInput);
|
||||
@ -334,6 +347,7 @@ function ChangeBackgroundImage()
|
||||
{
|
||||
// Don't show error message for image while user is typing
|
||||
ValidateAndPreviewImage(false);
|
||||
SetRelativeCheckbox();
|
||||
}
|
||||
|
||||
function ValidateAndPreviewImage(ShowErrorMessage)
|
||||
@ -347,7 +361,8 @@ function ValidateAndPreviewImage(ShowErrorMessage)
|
||||
{
|
||||
if (IsValidImage(image))
|
||||
{
|
||||
backgroundImage = image;
|
||||
backgroundImage = gHaveDocumentUrl ? MakeAbsoluteUrl(image) : image;
|
||||
|
||||
// Append image style
|
||||
styleValue += backImageStyle+backgroundImage+");";
|
||||
}
|
||||
|
||||
@ -133,23 +133,21 @@
|
||||
</groupbox>
|
||||
<spring class="spacer"/>
|
||||
<text class="label" value="&backgroundImage.label;"/>
|
||||
<grid flex="1">
|
||||
<columns><column flex="10"/><column flex="1"/></columns>
|
||||
<rows>
|
||||
<row autostretch="never" valign="middle" style="margin-bottom: 5px">
|
||||
<textbox id="BackgroundImageInput" oninput="ChangeBackgroundImage()"
|
||||
tooltip="aTooltip" tooltiptext="&backgroundImage.tooltip;"
|
||||
style="min-width : 21em"/>
|
||||
<!-- from EdDialogOverlay.xul -->
|
||||
<button class="dialog" id="ChooseFile"/>
|
||||
</row>
|
||||
<row autostretch="never" valign="middle">
|
||||
<spring flex="1"/>
|
||||
<!-- from EdDialogOverlay.xul -->
|
||||
<button class="dialog" id="AdvancedEditButton"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<hbox>
|
||||
<textbox id="BackgroundImageInput" oninput="ChangeBackgroundImage()"
|
||||
tooltip="aTooltip" tooltiptext="&backgroundImage.tooltip;"
|
||||
style="min-width : 21em"/>
|
||||
<!-- from EdDialogOverlay.xul -->
|
||||
<button class="dialog" id="ChooseFile"/>
|
||||
</hbox>
|
||||
<!-- from EdDialogOverlay.xul 'for' identifies the textfield to get URL from -->
|
||||
<checkbox id="MakeRelativeCheckbox" for="BackgroundImageInput"/>
|
||||
<spring class="smallspacer"/>
|
||||
<hbox>
|
||||
<spring flex="1"/>
|
||||
<!-- from EdDialogOverlay.xul -->
|
||||
<button class="dialog" id="AdvancedEditButton"/>
|
||||
</hbox>
|
||||
<separator class="groove"/>
|
||||
<hbox id="okCancelButtons"/>
|
||||
<hbox id="okCancelButtonsRight"/>
|
||||
</window>
|
||||
|
||||
@ -44,6 +44,11 @@ var gOutputAbsoluteLinks = 128;
|
||||
var gOutputEncodeEntities = 256;
|
||||
var gStringBundle;
|
||||
var gValidationError = false;
|
||||
var gIOService;
|
||||
var gOS = "";
|
||||
const gWin = "Win";
|
||||
const gUNIX = "UNIX";
|
||||
const gMac = "Mac";
|
||||
|
||||
// Use for 'defaultIndex' param in InitPixelOrPercentMenulist
|
||||
var gPixel = 0;
|
||||
@ -1172,3 +1177,365 @@ function TextIsURI(selectedText)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function SetRelativeCheckbox()
|
||||
{
|
||||
var checkbox = document.getElementById("MakeRelativeCheckbox");
|
||||
if (!checkbox)
|
||||
return;
|
||||
|
||||
var input = document.getElementById(checkbox.getAttribute("for"));
|
||||
if (!input)
|
||||
return;
|
||||
|
||||
var url = TrimString(input.value);
|
||||
var urlScheme = GetScheme(url);
|
||||
|
||||
// Check it if url is relative (no scheme).
|
||||
checkbox.checked = url.length > 0 && !urlScheme;
|
||||
|
||||
// Now do checkbox enabling:
|
||||
var enable = false;
|
||||
|
||||
var docUrl = GetDocumentBaseUrl();
|
||||
var docScheme = GetScheme(docUrl);
|
||||
|
||||
if (url && docUrl && docScheme)
|
||||
{
|
||||
if (urlScheme)
|
||||
{
|
||||
// Url is absolute, scheme and host must be the same
|
||||
if (urlScheme == docScheme)
|
||||
{
|
||||
var urlHost = GetHost(url);
|
||||
var docHost = GetHost(docUrl);
|
||||
enable = (urlHost == docHost);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Url is relative
|
||||
// Check if url is a named anchor
|
||||
// but document doesn't have a filename
|
||||
// (it's probably "index.html" or "index.htm",
|
||||
// but we don't want to allow a malformed URL)
|
||||
if (url[0] == "#")
|
||||
{
|
||||
var docFilename = GetFilename(docUrl);
|
||||
enable = docFilename.length > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Any other url is assumed
|
||||
// to be ok to try to make absolute
|
||||
enable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetElementEnabledById("MakeRelativeCheckbox", enable);
|
||||
}
|
||||
|
||||
// oncommand handler for the Relativize checkbox in EditorOverlay.xul
|
||||
function MakeInputValueRelativeOrAbsolute()
|
||||
{
|
||||
var checkbox = document.getElementById("MakeRelativeCheckbox");
|
||||
if (!checkbox)
|
||||
return;
|
||||
|
||||
var input = document.getElementById(checkbox.getAttribute("for"));
|
||||
if (!input)
|
||||
return;
|
||||
|
||||
var docUrl = GetDocumentBaseUrl();
|
||||
if (!docUrl)
|
||||
{
|
||||
// Checkbox should be disabled if not saved,
|
||||
// but keep this error message in case we change that
|
||||
AlertWithTitle("", GetString("SaveToUseRelativeUrl"));
|
||||
window.focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note that "checked" is opposite of its last state,
|
||||
// which determines what we want to do here
|
||||
if (checkbox.checked)
|
||||
input.value = MakeRelativeUrl(input.value);
|
||||
else
|
||||
input.value = MakeAbsoluteUrl(input.value);
|
||||
|
||||
// Reset checkbox to reflect url state
|
||||
SetRelativeCheckbox(checkbox, input.value);
|
||||
}
|
||||
}
|
||||
|
||||
function MakeRelativeUrl(url)
|
||||
{
|
||||
var inputUrl = TrimString(url);
|
||||
if (!inputUrl)
|
||||
return inputUrl;
|
||||
|
||||
// Get the filespec relative to current document's location
|
||||
// NOTE: Can't do this if file isn't saved yet!
|
||||
var docUrl = GetDocumentBaseUrl();
|
||||
var docScheme = GetScheme(docUrl);
|
||||
|
||||
// Can't relativize if no doc scheme (page hasn't been saved)
|
||||
if (!docScheme)
|
||||
return inputUrl;
|
||||
|
||||
var urlScheme = GetScheme(inputUrl);
|
||||
|
||||
// Do nothing if not the same scheme or url is already relativized
|
||||
if (docScheme != urlScheme)
|
||||
return inputUrl;
|
||||
|
||||
var IOService = GetIOService();
|
||||
if (!IOService)
|
||||
return inputUrl;
|
||||
|
||||
// Host must be the same
|
||||
var docHost = GetHost(docUrl);
|
||||
var urlHost = GetHost(inputUrl);
|
||||
if (docHost != urlHost)
|
||||
return inputUrl;
|
||||
|
||||
// Get just the file path part of the urls
|
||||
var docPath = IOService.extractUrlPart(docUrl, IOService.url_Directory, {start:0}, {end:0});
|
||||
var urlPath = IOService.extractUrlPart(inputUrl, IOService.url_Directory, {start:0}, {end:0});
|
||||
|
||||
// We only return "urlPath", so we can convert
|
||||
// the entire docPath for case-insensitive comparisons
|
||||
var os = GetOS();
|
||||
var doCaseInsensitive = (docScheme.toLowerCase() == "file" && os == gWin);
|
||||
if (doCaseInsensitive)
|
||||
docPath = docPath.toLowerCase();
|
||||
|
||||
// Get document filename before we start chopping up the docPath
|
||||
var docFilename = GetFilename(docPath);
|
||||
|
||||
// Both url and doc paths now begin with "/"
|
||||
// Look for shared dirs starting after that
|
||||
urlPath = urlPath.slice(1);
|
||||
docPath = docPath.slice(1);
|
||||
|
||||
var firstDirTest = true;
|
||||
var nextDocSlash = 0;
|
||||
var done = false;
|
||||
|
||||
// Remove all matching subdirs common to both doc and input urls
|
||||
do {
|
||||
nextDocSlash = docPath.indexOf("\/");
|
||||
var nextUrlSlash = urlPath.indexOf("\/");
|
||||
|
||||
if (nextUrlSlash == -1)
|
||||
{
|
||||
// We're done matching and all dirs in url
|
||||
// what's left is the filename
|
||||
done = true;
|
||||
|
||||
// Remove filename for named anchors in the same file
|
||||
if (nextDocSlash == -1 && docFilename)
|
||||
{
|
||||
var anchorIndex = urlPath.indexOf("#");
|
||||
if (anchorIndex > 0)
|
||||
{
|
||||
var urlFilename = doCaseInsensitive ? urlPath.toLowerCase() : urlPath;
|
||||
|
||||
if (urlFilename.indexOf(docFilename) == 0)
|
||||
urlPath = urlPath.slice(anchorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nextDocSlash >= 0)
|
||||
{
|
||||
// Test for matching subdir
|
||||
var docDir = docPath.slice(0, nextDocSlash);
|
||||
var urlDir = urlPath.slice(0, nextUrlSlash);
|
||||
if (doCaseInsensitive)
|
||||
urlDir = urlDir.toLowerCase();
|
||||
|
||||
if (urlDir == docDir)
|
||||
{
|
||||
|
||||
// Remove matching dir+"/" from each path
|
||||
// and continue to next dir
|
||||
docPath = docPath.slice(nextDocSlash+1);
|
||||
urlPath = urlPath.slice(nextUrlSlash+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match, we're done
|
||||
done = true;
|
||||
|
||||
// Be sure we are on the same local drive or volume
|
||||
// (the first "dir" in the path) because we can't
|
||||
// relativize to different drives/volumes.
|
||||
// UNIX doesn't have volumes, so we must not do this else
|
||||
// the first directory will be misinterpreted as a volume name
|
||||
if (firstDirTest && docScheme == "file" && os != gUNIX)
|
||||
return inputUrl;
|
||||
}
|
||||
}
|
||||
else // No more doc dirs left, we're done
|
||||
done = true;
|
||||
|
||||
firstDirTest = false;
|
||||
}
|
||||
while (!done);
|
||||
|
||||
// Add "../" for each dir left in docPath
|
||||
while (nextDocSlash > 0)
|
||||
{
|
||||
urlPath = "../" + urlPath;
|
||||
nextDocSlash = docPath.indexOf("\/", nextDocSlash+1);
|
||||
}
|
||||
return urlPath;
|
||||
}
|
||||
|
||||
function MakeAbsoluteUrl(url)
|
||||
{
|
||||
var resultUrl = TrimString(url);
|
||||
if (!resultUrl)
|
||||
return resultUrl;
|
||||
|
||||
// Check if URL is already absolute, i.e., it has a scheme
|
||||
var urlScheme = GetScheme(resultUrl);
|
||||
|
||||
if (urlScheme)
|
||||
return resultUrl;
|
||||
|
||||
var docUrl = GetDocumentBaseUrl();
|
||||
var docScheme = GetScheme(docUrl);
|
||||
|
||||
// Can't relativize if no doc scheme (page hasn't been saved)
|
||||
if (!docScheme)
|
||||
return resultUrl;
|
||||
|
||||
var IOService = GetIOService();
|
||||
if (!IOService)
|
||||
return resultUrl;
|
||||
|
||||
// Make a URI object to use its "resolve" method
|
||||
var absoluteUrl = resultUrl;
|
||||
var docUri = IOService.newURI(docUrl, null);
|
||||
|
||||
try {
|
||||
absoluteUrl = docUri.resolve(resultUrl);
|
||||
// This is deprecated and buggy!
|
||||
// If used, we must make it a path for the parent directory (remove filename)
|
||||
//absoluteUrl = IOService.resolveRelativePath(resultUrl, docUrl);
|
||||
} catch (e) {}
|
||||
|
||||
return absoluteUrl;
|
||||
}
|
||||
|
||||
// Get the HREF of the page's <base> tag or the document location
|
||||
// returns empty string if no base href and document hasn't been saved yet
|
||||
function GetDocumentBaseUrl()
|
||||
{
|
||||
if (window.editorShell)
|
||||
{
|
||||
var docUrl;
|
||||
|
||||
// if document supplies a <base> tag, use that URL instead
|
||||
var baseList = editorShell.editorDocument.getElementsByTagName("base");
|
||||
if (baseList)
|
||||
{
|
||||
var base = baseList.item(0);
|
||||
if (base)
|
||||
docUrl = base.getAttribute("href");
|
||||
}
|
||||
if (!docUrl)
|
||||
docUrl = editorShell.editorDocument.location.href;
|
||||
|
||||
if (docUrl != "about:blank")
|
||||
return docUrl;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function GetIOService()
|
||||
{
|
||||
if (gIOService)
|
||||
return gIOService;
|
||||
|
||||
var CID = Components.classes["@mozilla.org/network/io-service;1"];
|
||||
gIOService = CID.getService(Components.interfaces.nsIIOService);
|
||||
return gIOService;
|
||||
}
|
||||
|
||||
// Extract the scheme (e.g., 'file', 'http') from a URL string
|
||||
function GetScheme(url)
|
||||
{
|
||||
var resultUrl = TrimString(url);
|
||||
// Unsaved document URL has no acceptable scheme yet
|
||||
if (!resultUrl || resultUrl == "about:blank")
|
||||
return "";
|
||||
|
||||
var IOService = GetIOService();
|
||||
if (!IOService)
|
||||
return "";
|
||||
|
||||
var scheme = "";
|
||||
try {
|
||||
// This fails if there's no scheme
|
||||
scheme = IOService.extractScheme(resultUrl, {schemeStartPos:0}, {schemeEndPos:0});
|
||||
} catch (e) {}
|
||||
|
||||
return scheme ? scheme : "";
|
||||
}
|
||||
|
||||
function GetHost(url)
|
||||
{
|
||||
var IOService = GetIOService();
|
||||
if (!IOService)
|
||||
return "";
|
||||
|
||||
var host = "";
|
||||
if (url)
|
||||
{
|
||||
try {
|
||||
host = IOService.extractUrlPart(url, IOService.url_Host, {start:0}, {end:0});
|
||||
} catch (e) {}
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
function GetFilename(url)
|
||||
{
|
||||
var IOService = GetIOService();
|
||||
if (!IOService)
|
||||
return "";
|
||||
|
||||
var filename;
|
||||
|
||||
if (url)
|
||||
{
|
||||
try {
|
||||
filename = IOService.extractUrlPart(url, IOService.url_FileBaseName, {start:0}, {end:0});
|
||||
if (filename)
|
||||
{
|
||||
var ext = IOService.extractUrlPart(url, IOService.url_FileExtension, {start:0}, {end:0});
|
||||
if (ext)
|
||||
filename += "."+ext;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
return filename ? filename : "";
|
||||
}
|
||||
|
||||
function GetOS()
|
||||
{
|
||||
if (gOS)
|
||||
return gOS;
|
||||
|
||||
if (navigator.platform.toLowerCase().indexOf("win") >= 0)
|
||||
gOS = gWin;
|
||||
else if (navigator.platform.toLowerCase().indexOf("mac") >=0)
|
||||
gOS = gMac;
|
||||
else
|
||||
gOS = gUNIX;
|
||||
|
||||
return gOS;
|
||||
}
|
||||
|
||||
@ -64,4 +64,12 @@
|
||||
oncommand = "chooseFile()"
|
||||
label = "&chooseButton.label;"/>
|
||||
|
||||
<checkbox
|
||||
id = "MakeRelativeCheckbox"
|
||||
label = "&makeUrlRelative.label;"
|
||||
oncommand = "MakeInputValueRelativeOrAbsolute()"
|
||||
tooltip = "aTooltip"
|
||||
tooltiptext = "&makeUrlRelative.tooltip;"
|
||||
style = "margin-top: 0px"/>
|
||||
|
||||
</overlay>
|
||||
|
||||
@ -42,6 +42,7 @@ var doAltTextError = false;
|
||||
var actualWidth = "";
|
||||
var gOriginalSrc = "";
|
||||
var actualHeight = "";
|
||||
var gHaveDocumentUrl = false;
|
||||
|
||||
// These must correspond to values in EditorDialog.css for each theme
|
||||
// (unfortunately, setting "style" attribute here doesn't work!)
|
||||
@ -74,11 +75,9 @@ function Startup()
|
||||
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.actualSizeRadio = document.getElementById( "actualSizeRadio" );
|
||||
dialog.actualSizeRadio = document.getElementById( "actualSizeRadio" );
|
||||
dialog.constrainCheckbox = document.getElementById( "constrainCheckbox" );
|
||||
dialog.widthInput = document.getElementById( "widthInput" );
|
||||
dialog.heightInput = document.getElementById( "heightInput" );
|
||||
@ -124,6 +123,9 @@ function Startup()
|
||||
// Make a copy to use for AdvancedEdit
|
||||
globalElement = imageElement.cloneNode(false);
|
||||
|
||||
// We only need to test for this once per dialog load
|
||||
gHaveDocumentUrl = GetDocumentBaseUrl();
|
||||
|
||||
InitDialog();
|
||||
|
||||
// Save initial source URL
|
||||
@ -155,8 +157,13 @@ function InitDialog()
|
||||
{
|
||||
// Set the controls to the image's attributes
|
||||
|
||||
dialog.srcInput.value= globalElement.getAttribute("src");
|
||||
GetImageFromURL();
|
||||
dialog.srcInput.value = globalElement.getAttribute("src");
|
||||
|
||||
// Set "Relativize" checkbox according to current URL state
|
||||
SetRelativeCheckbox();
|
||||
|
||||
// Force loading of image from its source and show preview image
|
||||
LoadPreviewImage();
|
||||
|
||||
dialog.altTextInput.value = globalElement.getAttribute("alt");
|
||||
|
||||
@ -244,10 +251,16 @@ function chooseFile()
|
||||
var fileName = GetLocalFileURL("img");
|
||||
if (fileName)
|
||||
{
|
||||
// Always try to relativize local file URLs
|
||||
if (gHaveDocumentUrl)
|
||||
fileName = MakeRelativeUrl(fileName);
|
||||
|
||||
dialog.srcInput.value = fileName;
|
||||
|
||||
SetRelativeCheckbox();
|
||||
doOverallEnabling();
|
||||
}
|
||||
GetImageFromURL();
|
||||
LoadPreviewImage();
|
||||
|
||||
// Put focus into the input field
|
||||
SetTextboxFocus(dialog.srcInput);
|
||||
@ -293,13 +306,13 @@ function PreviewImageLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
function GetImageFromURL()
|
||||
function LoadPreviewImage()
|
||||
{
|
||||
dialog.PreviewSize.setAttribute("collapsed", "true");
|
||||
|
||||
var imageSrc = dialog.srcInput.value;
|
||||
if (imageSrc) imageSrc = imageSrc.trimString();
|
||||
if (!imageSrc) return;
|
||||
var imageSrc = TrimString(dialog.srcInput.value);
|
||||
if (!imageSrc)
|
||||
return;
|
||||
|
||||
if (IsValidImage(dialog.srcInput.value))
|
||||
{
|
||||
@ -307,17 +320,27 @@ function GetImageFromURL()
|
||||
// Remove the image URL from image cache so it loads fresh
|
||||
// (if we don't do this, loads after the first will always use image cache
|
||||
// and we won't see image edit changes or be able to get actual width and height)
|
||||
|
||||
var IOService = GetIOService();
|
||||
if (IOService)
|
||||
{
|
||||
// We must have an absolute URL to preview it or remove it from the cache
|
||||
imageSrc = MakeAbsoluteUrl(imageSrc);
|
||||
|
||||
var uri = Components.classes["@mozilla.org/network/standard-url;1"]
|
||||
.createInstance(Components.interfaces.nsIURI);
|
||||
uri.spec = imageSrc;
|
||||
|
||||
var imgCacheService = Components.classes["@mozilla.org/image/cache;1"].getService();
|
||||
var imgCache = imgCacheService.QueryInterface(Components.interfaces.imgICache);
|
||||
|
||||
// This returns error if image wasn't in the cache; ignore that
|
||||
imgCache.removeEntry(uri);
|
||||
if (GetScheme(imageSrc))
|
||||
{
|
||||
var uri = IOService.newURI(imageSrc, null);
|
||||
if (uri)
|
||||
{
|
||||
var imgCacheService = Components.classes["@mozilla.org/image/cache;1"].getService();
|
||||
var imgCache = imgCacheService.QueryInterface(Components.interfaces.imgICache);
|
||||
|
||||
// This returns error if image wasn't in the cache; ignore that
|
||||
if (imgCache)
|
||||
imgCache.removeEntry(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
if(dialog.PreviewImage)
|
||||
@ -347,39 +370,11 @@ function SetActualSize()
|
||||
|
||||
function ChangeImageSrc()
|
||||
{
|
||||
GetImageFromURL();
|
||||
SetRelativeCheckbox();
|
||||
LoadPreviewImage();
|
||||
doOverallEnabling();
|
||||
}
|
||||
|
||||
// This overrides the default onMoreFewer in EdDialogCommon.js
|
||||
function onMoreFewer()
|
||||
{
|
||||
if (SeeMore)
|
||||
{
|
||||
dialog.MoreSection.setAttribute("collapsed","true");
|
||||
dialog.MoreFewerButton.setAttribute("label", GetString("MoreProperties"));
|
||||
dialog.MoreFewerButton.setAttribute("more","0");
|
||||
SeeMore = false;
|
||||
// Show the "Advanced Edit" button on same line as "More Properties"
|
||||
dialog.AdvancedEditButton.setAttribute("collapsed","false");
|
||||
dialog.AdvancedEditButton2.setAttribute("collapsed","true");
|
||||
// Weird caret appearing when we collapse, so force focus to URL textbox
|
||||
dialog.srcInput.focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
dialog.MoreSection.setAttribute("collapsed","false");
|
||||
dialog.MoreFewerButton.setAttribute("label", GetString("FewerProperties"));
|
||||
dialog.MoreFewerButton.setAttribute("more","1");
|
||||
SeeMore = true;
|
||||
|
||||
// Show the "Advanced Edit" button at bottom
|
||||
dialog.AdvancedEditButton.setAttribute("collapsed","true");
|
||||
dialog.AdvancedEditButton2.setAttribute("collapsed","false");
|
||||
}
|
||||
window.sizeToContent();
|
||||
}
|
||||
|
||||
function doDimensionEnabling()
|
||||
{
|
||||
// Enabled only if "Custom" is checked
|
||||
@ -414,7 +409,6 @@ function doOverallEnabling()
|
||||
wasEnableAll = canEnableOk;
|
||||
|
||||
SetElementEnabledById("ok", canEnableOk );
|
||||
|
||||
SetElementEnabledById( "imagemapLabel", canEnableOk );
|
||||
//TODO: Restore when Image Map editor is finished
|
||||
//SetElementEnabledById( "editImageMap", canEnableOk );
|
||||
|
||||
@ -57,35 +57,37 @@
|
||||
<groupbox orient="vertical">
|
||||
<caption label="&locationBox.label;"/>
|
||||
<!--/////// Src URL and ALT Text //////-->
|
||||
<grid>
|
||||
<columns><column/><column/><column flex="1"/></columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<text class = "label"
|
||||
for = "srcInput"
|
||||
value = "&locationEditField.label;"
|
||||
tooltip="aTooltip" tooltiptext="&locationEditField.tooltip;"
|
||||
/>
|
||||
<textbox
|
||||
id = "srcInput"
|
||||
oninput = "ChangeImageSrc()"
|
||||
style = "min-width : 20em"/>
|
||||
<!-- from EdDialogOverlay.xul -->
|
||||
<button id="ChooseFile"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<text class = "label"
|
||||
id = "altTextLabel"
|
||||
for = "altTextInput"
|
||||
tooltip = "aTooltip" tooltiptext="&altTextEditField.tooltip;"
|
||||
value = "&altTextEditField.label;" />
|
||||
<textbox
|
||||
id ="altTextInput"
|
||||
style = "min-width : 20em"/>
|
||||
<spring/> <!-- placeholder for 3rd column -->
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<text class = "label"
|
||||
for = "srcInput"
|
||||
value = "&locationEditField.label;"
|
||||
tooltip="aTooltip" tooltiptext="&locationEditField.tooltip;"
|
||||
/>
|
||||
<textbox
|
||||
id = "srcInput"
|
||||
oninput = "ChangeImageSrc()"
|
||||
style = "min-width : 20em"
|
||||
flex = "1"/>
|
||||
<hbox>
|
||||
<checkbox
|
||||
id = "MakeRelativeCheckbox"
|
||||
for = "srcInput"/>
|
||||
<spring flex="1"/>
|
||||
<!-- from EdDialogOverlay.xul -->
|
||||
<button id="ChooseFile"/>
|
||||
</hbox>
|
||||
<spring class="spacer"/>
|
||||
<hbox>
|
||||
<text class = "label"
|
||||
id = "altTextLabel"
|
||||
for = "altTextInput"
|
||||
tooltip = "aTooltip" tooltiptext="&altTextEditField.tooltip;"
|
||||
value = "&altTextEditField.label;"/>
|
||||
<textbox
|
||||
id ="altTextInput"
|
||||
style = "min-width : 20em"
|
||||
tooltip = "aTooltip" tooltiptext="&altTextEditField.tooltip;"
|
||||
flex = "1"/>
|
||||
</hbox>
|
||||
<spring class="spacer"/>
|
||||
</groupbox>
|
||||
<spring class="spacer"/>
|
||||
@ -96,8 +98,9 @@
|
||||
oncommand = "onMoreFewer()"
|
||||
tooltip = "aTooltip" tooltiptext = "&MoreFewerButton.tooltip;"
|
||||
persist = "more"/>
|
||||
<spring class="spacer"/>
|
||||
<groupbox style="padding: 4px">
|
||||
<spring class="bigspacer"/>
|
||||
<groupbox style="padding-left: 8px; padding-right: 8px">
|
||||
<caption label="&previewBox.label;"/>
|
||||
<hbox id="preview-image-box" align="center">
|
||||
<spring flex="1"/>
|
||||
<html id="preview-image-holder"/>
|
||||
@ -119,9 +122,6 @@
|
||||
<spring flex="1"/>
|
||||
</vbox>
|
||||
</groupbox>
|
||||
<spring flex="1"/>
|
||||
<!-- From EdDialogOverlay.xul -->
|
||||
<button id="AdvancedEditButton"/>
|
||||
</hbox>
|
||||
<spring class="spacer"/>
|
||||
<!-- Area that shows and hides via MoreFewerButton -->
|
||||
@ -288,16 +288,9 @@
|
||||
</groupbox>
|
||||
</vbox> <!-- Bottom Right region -->
|
||||
</hbox> <!-- The horizontal box -->
|
||||
|
||||
<!-- buttons along bottom -->
|
||||
<spring class="spacer"/>
|
||||
<hbox>
|
||||
<spring flex="1"/>
|
||||
<!-- From EdDialogOverlay -->
|
||||
<button id="AdvancedEditButton2"/>
|
||||
</hbox>
|
||||
</vbox> <!-- END OF MORE/FEWER SECTION -->
|
||||
<separator class="groove"/>
|
||||
<!-- from EdDialogOverlay -->
|
||||
<vbox id="AdvancedEdit"/>
|
||||
<!-- from global dialogOverlay -->
|
||||
<hbox id="okCancelHelpButtonsRight"/>
|
||||
</window>
|
||||
|
||||
@ -33,6 +33,7 @@ var gHaveNamedAnchors = false;
|
||||
var gHaveHeadings = false;
|
||||
var gCanChangeHeadingSelected = true;
|
||||
var gCanChangeAnchorSelected = true;
|
||||
var gHaveDocumentUrl = false;
|
||||
var dialog;
|
||||
|
||||
// NOTE: Use "href" instead of "a" to distinguish from Named Anchor
|
||||
@ -150,9 +151,10 @@ function Startup()
|
||||
if (insertLinkAtCaret)
|
||||
{
|
||||
// Groupbox caption:
|
||||
dialog.linkTextCaption.setAttribute("value",GetString("LinkText"));
|
||||
dialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
|
||||
|
||||
// Message above input field:
|
||||
dialog.linkTextMessage.setAttribute("value", GetString("EnterLinkText"));
|
||||
dialog.linkTextMessage.setAttribute("label", GetString("EnterLinkText"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -182,16 +184,16 @@ function Startup()
|
||||
// Set "caption" for link source and the source text or image URL
|
||||
if (imageElement)
|
||||
{
|
||||
dialog.linkTextCaption.setAttribute("value",GetString("LinkImage"));
|
||||
dialog.linkTextCaption.setAttribute("label",GetString("LinkImage"));
|
||||
// Link source string is the source URL of image
|
||||
// TODO: THIS DOESN'T HANDLE MULTIPLE SELECTED IMAGES!
|
||||
dialog.linkTextMessage.setAttribute("value",imageElement.src);
|
||||
} else {
|
||||
dialog.linkTextCaption.setAttribute("value",GetString("LinkText"));
|
||||
dialog.linkTextCaption.setAttribute("label",GetString("LinkText"));
|
||||
if (selectedText)
|
||||
{
|
||||
// Use just the first 40 characters and add "..."
|
||||
dialog.linkTextMessage.setAttribute("value",TruncateStringAtWordEnd(ReplaceWhitespace(selectedText, " "), 40, true));
|
||||
// Use just the first 60 characters and add "..."
|
||||
dialog.linkTextMessage.setAttribute("value",TruncateStringAtWordEnd(ReplaceWhitespace(selectedText, " "), 60, true));
|
||||
} else {
|
||||
dialog.linkTextMessage.setAttribute("value",GetString("MixedSelection"));
|
||||
}
|
||||
@ -204,6 +206,9 @@ function Startup()
|
||||
// Get the list of existing named anchors and headings
|
||||
FillListboxes();
|
||||
|
||||
// We only need to test for this once per dialog load
|
||||
gHaveDocumentUrl = GetDocumentBaseUrl();
|
||||
|
||||
// Set data for the dialog controls
|
||||
InitDialog();
|
||||
|
||||
@ -228,7 +233,7 @@ function Startup()
|
||||
InitMoreFewer();
|
||||
|
||||
// This sets enable state on OK button
|
||||
ChangeText();
|
||||
doEnabling();
|
||||
|
||||
SetWindowLocation();
|
||||
}
|
||||
@ -241,16 +246,25 @@ function InitDialog()
|
||||
// Must use getAttribute, not "globalElement.href",
|
||||
// or foreign chars aren't coverted correctly!
|
||||
dialog.hrefInput.value = globalElement.getAttribute("href");
|
||||
|
||||
// Set "Relativize" checkbox according to current URL state
|
||||
SetRelativeCheckbox();
|
||||
}
|
||||
|
||||
function chooseFile()
|
||||
{
|
||||
// Get a local file, converted into URL format
|
||||
var fileName = GetLocalFileURL("html");
|
||||
if (fileName) {
|
||||
if (fileName)
|
||||
{
|
||||
// Always try to relativize local file URLs
|
||||
if (gHaveDocumentUrl)
|
||||
fileName = MakeRelativeUrl(fileName);
|
||||
|
||||
dialog.hrefInput.value = fileName;
|
||||
// Call this to do OK button enabling
|
||||
ChangeText();
|
||||
|
||||
SetRelativeCheckbox();
|
||||
doEnabling();
|
||||
}
|
||||
// Put focus into the input field
|
||||
SetTextboxFocus(dialog.hrefInput);
|
||||
@ -322,10 +336,11 @@ function FillListboxes()
|
||||
}
|
||||
}
|
||||
|
||||
function ChangeText()
|
||||
function doEnabling()
|
||||
{
|
||||
// We disable Ok button when there's no href text only if inserting a new link
|
||||
var enable = insertNew ? (dialog.hrefInput.value.trimString().length > 0) : true;
|
||||
|
||||
SetElementEnabledById( "ok", enable);
|
||||
}
|
||||
|
||||
@ -339,8 +354,11 @@ function ChangeLocation()
|
||||
UnselectNamedAnchor();
|
||||
UnselectHeadings();
|
||||
}
|
||||
|
||||
SetRelativeCheckbox();
|
||||
|
||||
// Set OK button enable state
|
||||
ChangeText();
|
||||
doEnabling();
|
||||
}
|
||||
|
||||
function GetExistingHeadingIndex(text)
|
||||
@ -365,8 +383,10 @@ function SelectNamedAnchor()
|
||||
dialog.hrefInput.value = "#"+GetSelectedTreelistValue(dialog.NamedAnchorList);
|
||||
gClearListSelections = true;
|
||||
|
||||
SetRelativeCheckbox();
|
||||
|
||||
// ChangeLocation isn't always called, so be sure Ok is enabled
|
||||
ChangeText();
|
||||
doEnabling();
|
||||
}
|
||||
else
|
||||
UnselectNamedAnchor();
|
||||
@ -385,7 +405,8 @@ function SelectHeading()
|
||||
dialog.hrefInput.value = "#"+GetSelectedTreelistValue(dialog.HeadingsList);
|
||||
gClearListSelections = true;
|
||||
|
||||
ChangeText();
|
||||
SetRelativeCheckbox();
|
||||
doEnabling();
|
||||
}
|
||||
else
|
||||
UnselectHeadings();
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
<?xml-stylesheet href="chrome://editor/skin/EditorDialog.css" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
|
||||
<?xul-overlay href="chrome://editor/content/EdDialogOverlay.xul"?>
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://editor/locale/EditorLinkProperties.dtd">
|
||||
@ -45,20 +46,27 @@
|
||||
<broadcaster id="args" value=""/>
|
||||
<spring id="location" offsetY="50" persist="offsetX offsetY"/>
|
||||
<keyset id="dialogKeys"/>
|
||||
<popupset id="aTooltipSet" />
|
||||
|
||||
<vbox style="min-width: 20em">
|
||||
<groupbox orient="vertical"><caption id="linkTextCaption"/>
|
||||
<text class="label" id="linkTextMessage"/>
|
||||
<textbox id="linkTextInput" flex="1" oninput="ChangeText()"/>
|
||||
<textbox id="linkTextInput" flex="1"/>
|
||||
</groupbox>
|
||||
|
||||
<groupbox orient="vertical"><caption label="&LinkURLBox.label;"/>
|
||||
<text class="label" value="&LinkURLEditField.label;"/>
|
||||
<hbox autostretch="never" valign="middle">
|
||||
<textbox id="hrefInput" flex="1" style="min-width: 18em" oninput="ChangeLocation()"/>
|
||||
</hbox>
|
||||
<hbox autostretch="never" valign="middle">
|
||||
<!-- from EdDialogOverlay.xul 'for' identifies the textfield to get URL from -->
|
||||
<checkbox id="MakeRelativeCheckbox" for="hrefInput"/>
|
||||
<spring flex="1"/>
|
||||
<button class="dialog" id="ChooseFile"/>
|
||||
</hbox>
|
||||
<html class="wrap" flex="1" id="RemoveLinkMsg" style="margin-bottom: 7px">&RemoveLinkMsg.label;</html>
|
||||
<spring class="smallspacer"/>
|
||||
<hbox autostretch="never">
|
||||
<button class="dialog" id="MoreFewerButton" oncommand="onMoreFewer()" persist="more"/>
|
||||
</hbox>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user