pjs/editor/ui/dialogs/content/EdLinkProps.js

413 строки
13 KiB
JavaScript
Исходник Обычный вид История

1999-08-19 18:28:44 +04:00
/*
* 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):
*/
var anchorElement = null;
var imageElement = null;
var insertNew = true;
var needLinkText = false;
1999-05-08 02:26:23 +04:00
var insertLinkAroundSelection = false;
var linkTextInput;
var hrefInput;
var linkMessage;
var href;
var newLinkText;
var NamedAnchorList = 0;
var HNodeArray;
var haveNamedAnchors = false;
var haveHeadings = false;
var MoreSection;
var MoreFewerButton;
var SeeMore = false;
var AdvancedEditSection;
// NOTE: Use "href" instead of "a" to distinguish from Named Anchor
// The returned node is has an "a" tagName
var tagName = "href";
// dialog initialization code
function Startup()
{
if (!InitEditorShell())
return;
1999-08-25 18:36:13 +04:00
doSetOKCancel(onOK, null);
// Message was wrapped in a <label> or <div>, so actual text is a child text node
linkCaption = (document.getElementById("linkTextCaption")).firstChild;
linkMessage = (document.getElementById("linkTextMessage")).firstChild;
linkTextInput = document.getElementById("linkTextInput");
hrefInput = document.getElementById("hrefInput");
NamedAnchorList = document.getElementById("NamedAnchorList");
HeadingsList = document.getElementById("HeadingsList");
MoreSection = document.getElementById("MoreSection");
MoreFewerButton = document.getElementById("MoreFewerButton");
AdvancedEditSection = document.getElementById("AdvancedEdit");
// Get a single selected anchor element
anchorElement = editorShell.GetSelectedElement(tagName);
1999-07-25 05:24:51 +04:00
var selection = editorShell.editorSelection;
if (selection) {
dump("There is a selection: collapsed = "+selection.isCollapsed+"\n");
} else {
dump("Failed to get selection\n");
}
if (anchorElement) {
// We found an element and don't need to insert one
1999-07-25 05:24:51 +04:00
dump("found anchor element\n");
insertNew = false;
1999-07-25 05:24:51 +04:00
// We get the anchor if any of the selection (or just caret)
// is enclosed by the link. Select the entire link
// so we can show the selection text
editorShell.SelectElement(anchorElement);
selection = editorShell.editorSelection;
} else {
// See if we have a selected image instead of text
imageElement = editorShell.GetSelectedElement("img");
if (imageElement) {
// See if the image is a child of a link
dump("Image element found - check if its a link...\n");
dump("Image Parent="+parent);
parent = imageElement.parentNode;
dump("Parent="+parent+" nodeName="+parent.nodeName+"\n");
if (parent) {
anchorElement = parent;
insertNew = false;
linkCaption.data = GetString("LinkImage");
// Link source string is the source URL of image
// TODO: THIS STILL DOESN'T HANDLE MULTIPLE SELECTED IMAGES!
linkMessage.data = imageElement.getAttribute("src");;
}
} else {
// We don't have an element selected,
// so create one with default attributes
dump("Element not selected - calling createElementWithDefaults\n");
anchorElement = editorShell.CreateElementWithDefaults(tagName);
// We will insert a new link at caret location if there's no selection
// TODO: This isn't entirely correct. If selection doesn't have any text
// or an image, then shouldn't we clear the selection and insert new text?
insertNew = selection.isCollapsed;
dump("insertNew is " + insertNew + "\n");
linkCaption.data = GetString("EnterLinkText");
linkMessage.data = "";
}
}
if(!anchorElement)
{
dump("Failed to get selected element or create a new one!\n");
window.close();
} else if (!insertNew && !imageElement) {
// Replace the link message with the link source string
selectedText = GetSelectionAsText();
if (selectedText.length > 0) {
// Use just the first 50 characters and add "..."
selectedText = TruncateStringAtWordEnd(selectedText, 50, true);
} else {
dump("Selected text for link source not found. Non-text elements selected?\n");
}
linkMessage.data = selectedText;
// The label above the selected text:
linkCaption.data = GetString("LinkText");
}
1999-05-08 02:26:23 +04:00
if (!selection.isCollapsed)
{
// HREF is a weird case: If selection extends beyond
// the link, user probably wants to extend link to
// entire selection.
// TODO: If there was already a link,
// we need to know if selection extends beyond existing
// link text before we should do this
insertLinkAroundSelection = true;
dump("insertLinkAroundSelection is TRUE\n");
}
// Make a copy to use for AdvancedEdit and onSaveDefault
globalElement = anchorElement.cloneNode(false);
// Get the list of existing named anchors and headings
FillListboxes();
// Set data for the dialog controls
InitDialog();
// Set initial focus
if (insertNew) {
dump("Setting focus to linkTextInput\n");
// We will be using the HREF inputbox, so text message
linkTextInput.focus();
} else {
dump("Setting focus to linkTextInput\n");
hrefInput.focus();
// We will not insert a new link at caret, so remove link text input field
parentNode = linkTextInput.parentNode;
if (parentNode) {
dump("Removing link text input field.\n");
parentNode.removeChild(linkTextInput);
linkTextInput = 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
// onMoreFewer will toggle it and redraw the dialog
SeeMore = (MoreFewerButton.getAttribute("more") != "1");
onMoreFewer();
}
// 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()
{
hrefInput.value = globalElement.getAttribute("href");
dump("Current HREF: "+hrefInput.value+"\n");
}
function chooseFile()
{
// Get a local file, converted into URL format
fileName = editorShell.GetLocalFileURL(window, "html");
if (fileName) {
hrefInput.value = fileName;
}
// Put focus into the input field
hrefInput.focus();
}
function RemoveLink()
{
// Simple clear the input field!
hrefInput.value = "";
}
function FillListboxes()
{
NamedAnchorNodeList = editorShell.editorDocument.anchors;
var NamedAnchorCount = NamedAnchorNodeList.length;
if (NamedAnchorCount > 0) {
for (var i = 0; i < NamedAnchorCount; i++) {
AppendStringToList(NamedAnchorList,NamedAnchorNodeList.item(i).name);
}
haveNamedAnchors = true;
} else {
// Message to tell user there are none
AppendStringToList(NamedAnchorList,GetString("NoNamedAnchors"));
NamedAnchorList.setAttribute("disabled", "true");
}
var firstHeading = true;
for (var j = 1; j <= 6; j++) {
var headingList = editorShell.editorDocument.getElementsByTagName("h"+String(j));
dump(headingList+" Count= "+headingList.length+"\n");
if (headingList.length > 0) {
dump("HELLO\n");
var heading = headingList.item(0);
// Skip headings that already have a named anchor as their first child
// (this may miss nearby anchors, but at least we don't insert another
// under the same heading)
var child = heading.firstChild;
if( child && child.name )
dump(child.name+" = Child.name. Length="+child.name.length+"\n");
if (child && child.nodeName == "A" && child.name && (child.name.length>0)) {
continue;
}
var range = editorShell.editorDocument.createRange();
range.setStart(heading,0);
var lastChildIndex = heading.childNodes.length;
range.setEnd(heading,lastChildIndex);
var text = range.toString();
if (text) {
// Use just first 40 characters, don't add "...",
// and replace whitespace with "_" and strip non-word characters
text = PrepareStringForURL(TruncateStringAtWordEnd(text, 40, false));
// Append "_" to any name already in the list
if (GetExistingHeadingIndex(text) > -1)
text += "_";
AppendStringToList(HeadingsList, text);
// Save nodes in an array so we can create anchor node under it later
if (!HNodeArray)
HNodeArray = new Array(heading)
else
HNodeArray[HNodeArray.length] = heading;
}
}
}
if (HNodeArray) {
haveHeadings = true;
} else {
// Message to tell user there are none
AppendStringToList(HeadingsList,GetString("NoHeadings"));
HeadingsList.setAttribute("disabled", "true");
}
}
function GetExistingHeadingIndex(text)
{
dump("Heading text: "+text+"\n");
for (i=0; i < HeadingsList.length; i++) {
dump("HeadingListItem"+i+": "+HeadingsList.options[i].value+"\n");
if (HeadingsList.options[i].value == text)
return i;
}
return -1;
}
function SelectNamedAnchor()
{
if (haveNamedAnchors) {
hrefInput.value = "#"+NamedAnchorList.options[NamedAnchorList.selectedIndex].value;
}
}
function SelectHeading()
{
if (haveHeadings) {
hrefInput.value = "#"+HeadingsList.options[HeadingsList.selectedIndex].value;
}
}
function onMoreFewer()
{
if (SeeMore)
{
MoreSection.setAttribute("style","display: none");
window.sizeToContent();
MoreFewerButton.setAttribute("more","0");
MoreFewerButton.setAttribute("value",GetString("MoreProperties"));
SeeMore = false;
}
else
{
MoreSection.setAttribute("style","display: inherit");
window.sizeToContent();
MoreFewerButton.setAttribute("more","1");
MoreFewerButton.setAttribute("value",GetString("FewerProperties"));
SeeMore = true;
}
}
// Get and validate data from widgets.
// Set attributes on globalElement so they can be accessed by AdvancedEdit()
function ValidateData()
{
href = hrefInput.value.trimString();
if (href.length > 0) {
// Set the HREF directly on the editor document's anchor node
// or on the newly-created node if insertNew is true
globalElement.setAttribute("href",href);
dump("HREF:"+href+"|\n");
} else if (insertNew) {
// We must have a URL to insert a new link
//NOTE: WE ACCEPT AN EMPTY HREF TO ALLOW REMOVING AN EXISTING LINK,
dump("Empty HREF error\n");
ShowInputErrorMessage(GetString("EmptyHREFError"));
return false;
}
if (linkTextInput) {
// The text we will insert isn't really an attribute,
// but it makes sense to validate it
newLinkText = TrimString(linkTextInput.value);
if (newLinkText.length == 0) {
ShowInputErrorMessage(GetString("GetInputError"));
linkTextInput.focus();
return false;
}
}
return true;
}
function onOK()
{
if (ValidateData())
{
if (href.length > 0) {
// Copy attributes to element we are changing or inserting
editorShell.CloneAttributes(anchorElement, globalElement);
// Coalesce into one undo transaction
editorShell.BeginBatchChanges();
// Get text to use for a new link
if (insertNew) {
// Append the link text as the last child node
// of the anchor node
textNode = editorShell.editorDocument.createTextNode(newLinkText);
if (textNode) {
anchorElement.appendChild(textNode);
}
try {
editorShell.InsertElementAtSelection(anchorElement, false);
} catch (e) {
dump("Exception occured in InsertElementAtSelection\n");
return true;
}
} else if (insertLinkAroundSelection) {
// Text was supplied by the selection,
// so insert a link node as parent of this text
try {
editorShell.InsertLinkAroundSelection(anchorElement);
} catch (e) {
dump("Exception occured in InsertElementAtSelection\n");
return true;
}
}
// Check if the link was to a heading
if (href[0] == "#") {
var name = href.substr(1);
var index = GetExistingHeadingIndex(name);
dump("Heading name="+name+" Index="+index+"\n");
if (index >= 0) {
// We need to create a named anchor
// and insert it as the first child of the heading element
var headNode = HNodeArray[index];
var anchorNode = editorShell.editorDocument.createElement("a");
if (anchorNode) {
anchorNode.name = name;
// Remember to use editorShell method so it is undoable!
editorShell.InsertElement(anchorNode, headNode, 0);
dump("Anchor node created and inserted under heading\n");
}
} else {
dump("HREF is a heading but is not in the list!\n");
}
}
editorShell.EndBatchChanges();
} else if (!insertNew) {
// We already had a link, but empty HREF means remove it
editorShell.RemoveTextProperty("a", "");
}
return true;
}
return false;
}