home *** CD-ROM | disk | FTP | other *** search
/ ftp.swcp.com / ftp.swcp.com.zip / ftp.swcp.com / mac / mozilla-macos9-1.3.1.sea.bin / Mozilla1.3.1 / Chrome / comm.jar / content / editor / EdLinkProps.js < prev    next >
Text File  |  2003-06-08  |  12KB  |  367 lines

  1. /* 
  2.  * The contents of this file are subject to the Netscape Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/NPL/
  6.  *  
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  *  
  12.  * The Original Code is Mozilla Communicator client code, released
  13.  * March 31, 1998.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation. Portions created by Netscape are
  17.  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s): 
  21.  *    Charles Manske (cmanske@netscape.com)
  22.  *    Neil Rashbrook (neil@parkwaycc.co.uk)
  23.  */
  24.  
  25. var gActiveEditor;
  26. var anchorElement = null;
  27. var imageElement = null;
  28. var insertNew = false;
  29. var replaceExistingLink = false;
  30. var insertLinkAtCaret;
  31. var needLinkText = false;
  32. var href;
  33. var newLinkText;
  34. var gHNodeArray = {};
  35. var gHaveNamedAnchors = false;
  36. var gHaveHeadings = false;
  37. var gCanChangeHeadingSelected = true;
  38. var gCanChangeAnchorSelected = true;
  39. var gHaveDocumentUrl = false;
  40.  
  41. // NOTE: Use "href" instead of "a" to distinguish from Named Anchor
  42. // The returned node is has an "a" tagName
  43. var tagName = "href";
  44.  
  45. // dialog initialization code
  46. function Startup()
  47. {
  48.   gActiveEditor = GetCurrentEditor();
  49.   if (!gActiveEditor)
  50.   {
  51.     dump("Failed to get active editor!\n");
  52.     window.close();
  53.     return;
  54.   }
  55.   // Message was wrapped in a <label> or <div>, so actual text is a child text node
  56.   gDialog.linkTextCaption     = document.getElementById("linkTextCaption");
  57.   gDialog.linkTextMessage     = document.getElementById("linkTextMessage");
  58.   gDialog.linkTextInput       = document.getElementById("linkTextInput");
  59.   gDialog.hrefInput           = document.getElementById("hrefInput");
  60.   gDialog.makeRelativeLink    = document.getElementById("MakeRelativeLink");
  61.   gDialog.AdvancedEditSection = document.getElementById("AdvancedEdit");
  62.  
  63.   // See if we have a single selected image
  64.   imageElement = gActiveEditor.getSelectedElement("img");
  65.  
  66.   if (imageElement)
  67.   {
  68.     // Get the parent link if it exists -- more efficient than GetSelectedElement()
  69.     anchorElement = gActiveEditor.getElementOrParentByTagName("href", imageElement);
  70.     if (anchorElement)
  71.     {
  72.       if (anchorElement.childNodes.length > 1)
  73.       {
  74.         // If there are other children, then we want to break
  75.         //  this image away by inserting a new link around it,
  76.         //  so make a new node and copy existing attributes
  77.         anchorElement = anchorElement.cloneNode(false);
  78.         //insertNew = true;
  79.         replaceExistingLink = true;
  80.       }
  81.     }
  82.   }
  83.   else
  84.   {
  85.     // Get an anchor element if caret or
  86.     //   entire selection is within the link.
  87.     anchorElement = gActiveEditor.getSelectedElement(tagName);
  88.  
  89.     if (anchorElement)
  90.     {
  91.       // Select the entire link
  92.       gActiveEditor.selectElement(anchorElement);
  93.     }
  94.     else
  95.     {
  96.       // If selection starts in a link, but extends beyond it,
  97.       //   the user probably wants to extend existing link to new selection,
  98.       //   so check if either end of selection is within a link
  99.       // POTENTIAL PROBLEM: This prevents user from selecting text in an existing
  100.       //   link and making 2 links. 
  101.       // Note that this isn't a problem with images, handled above
  102.  
  103.       anchorElement = gActiveEditor.getElementOrParentByTagName("href", gActiveEditor.selection.anchorNode);
  104.       if (!anchorElement)
  105.         anchorElement = gActiveEditor.getElementOrParentByTagName("href", gActiveEditor.selection.focusNode);
  106.  
  107.       if (anchorElement)
  108.       {
  109.         // But clone it for reinserting/merging around existing
  110.         //   link that only partially overlaps the selection
  111.         anchorElement = anchorElement.cloneNode(false);
  112.         //insertNew = true;
  113.         replaceExistingLink = true;
  114.       }
  115.     }
  116.   }
  117.  
  118.   if(!anchorElement)
  119.   {
  120.     // No existing link -- create a new one
  121.     anchorElement = gActiveEditor.createElementWithDefaults(tagName);
  122.     insertNew = true;
  123.     // Hide message about removing existing link
  124.     //document.getElementById("RemoveLinkMsg").hidden = true;
  125.   }
  126.   if(!anchorElement)
  127.   {
  128.     dump("Failed to get selected element or create a new one!\n");
  129.     window.close();
  130.     return;
  131.   } 
  132.  
  133.   // We insert at caret only when nothing is selected
  134.   insertLinkAtCaret = gActiveEditor.selection.isCollapsed;
  135.   
  136.   var selectedText;
  137.   if (insertLinkAtCaret)
  138.   {
  139.     // Groupbox caption:
  140.     gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
  141.  
  142.     // Message above input field:
  143.     gDialog.linkTextMessage.setAttribute("value", GetString("EnterLinkText"));
  144.     gDialog.linkTextMessage.setAttribute("accesskey", GetString("EnterLinkTextAccessKey"));
  145.   }
  146.   else
  147.   {
  148.     if (!imageElement)
  149.     {
  150.       // We get here if selection is exactly around a link node
  151.       // Check if selection has some text - use that first
  152.       selectedText = GetSelectionAsText();
  153.       if (!selectedText) 
  154.       {
  155.         // No text, look for first image in the selection
  156.         var children = anchorElement.childNodes;
  157.         if (children)
  158.         {
  159.           for(var i=0; i < children.length; i++) 
  160.           {
  161.             var nodeName = children.item(i).nodeName.toLowerCase();
  162.             if (nodeName == "img")
  163.             {
  164.               imageElement = children.item(i);
  165.               break;
  166.             }
  167.           }
  168.         }
  169.       }
  170.     }
  171.     // Set "caption" for link source and the source text or image URL
  172.     if (imageElement)
  173.     {
  174.       gDialog.linkTextCaption.setAttribute("label", GetString("LinkImage"));
  175.       // Link source string is the source URL of image
  176.       // TODO: THIS DOESN'T HANDLE MULTIPLE SELECTED IMAGES!
  177.       gDialog.linkTextMessage.setAttribute("value", imageElement.src);
  178.     } else {
  179.       gDialog.linkTextCaption.setAttribute("label", GetString("LinkText"));
  180.       if (selectedText) 
  181.       {
  182.         // Use just the first 60 characters and add "..."
  183.         gDialog.linkTextMessage.setAttribute("value", TruncateStringAtWordEnd(ReplaceWhitespace(selectedText, " "), 60, true));
  184.       } else {
  185.         gDialog.linkTextMessage.setAttribute("value", GetString("MixedSelection"));
  186.       }
  187.     }
  188.   }
  189.  
  190.   // Make a copy to use for AdvancedEdit and onSaveDefault
  191.   globalElement = anchorElement.cloneNode(false);
  192.  
  193.   // Get the list of existing named anchors and headings
  194.   FillLinkMenulist(gDialog.hrefInput, gHNodeArray);
  195.  
  196.   // We only need to test for this once per dialog load
  197.   gHaveDocumentUrl = GetDocumentBaseUrl();
  198.  
  199.   // Set data for the dialog controls
  200.   InitDialog();
  201.   
  202.   // Search for a URI pattern in the selected text
  203.   //  as candidate href
  204.   selectedText = TrimString(selectedText); 
  205.   if (!gDialog.hrefInput.value && TextIsURI(selectedText))
  206.       gDialog.hrefInput.value = selectedText;
  207.  
  208.   // Set initial focus
  209.   if (insertLinkAtCaret) {
  210.     // We will be using the HREF inputbox, so text message
  211.     SetTextboxFocus(gDialog.linkTextInput);
  212.   } else {
  213.     SetTextboxFocus(gDialog.hrefInput);
  214.  
  215.     // We will not insert a new link at caret, so remove link text input field
  216.     gDialog.linkTextInput.hidden = true;
  217.     gDialog.linkTextInput = null;
  218.   }
  219.     
  220.   // This sets enable state on OK button
  221.   doEnabling();
  222.  
  223.   SetWindowLocation();
  224. }
  225.  
  226. // Set dialog widgets with attribute data
  227. // We get them from globalElement copy so this can be used
  228. //   by AdvancedEdit(), which is shared by all property dialogs
  229. function InitDialog()
  230. {
  231.   // Must use getAttribute, not "globalElement.href", 
  232.   //  or foreign chars aren't coverted correctly!
  233.   gDialog.hrefInput.value = globalElement.getAttribute("href");
  234.  
  235.   // Set "Relativize" checkbox according to current URL state
  236.   SetRelativeCheckbox(gDialog.makeRelativeLink);
  237. }
  238.  
  239. function doEnabling()
  240. {
  241.   // We disable Ok button when there's no href text only if inserting a new link
  242.   var enable = insertNew ? (TrimString(gDialog.hrefInput.value).length > 0) : true;
  243.   
  244.   // anon. content, so can't use SetElementEnabledById here
  245.   var dialogNode = document.getElementById("linkDlg");
  246.   dialogNode.getButton("accept").disabled = !enable;
  247.  
  248.   SetElementEnabledById( "AdvancedEditButton1", enable);
  249. }
  250.  
  251. function ChangeLinkLocation()
  252. {
  253.   SetRelativeCheckbox();
  254.   // Set OK button enable state
  255.   doEnabling();
  256. }
  257.  
  258. // Get and validate data from widgets.
  259. // Set attributes on globalElement so they can be accessed by AdvancedEdit()
  260. function ValidateData()
  261. {
  262.   href = TrimString(gDialog.hrefInput.value);
  263.   if (href)
  264.   {
  265.     // Set the HREF directly on the editor document's anchor node
  266.     //  or on the newly-created node if insertNew is true
  267.     globalElement.setAttribute("href",href);
  268.   }
  269.   else if (insertNew)
  270.   {
  271.     // We must have a URL to insert a new link
  272.     //NOTE: We accept an empty HREF on existing link to indicate removing the link
  273.     ShowInputErrorMessage(GetString("EmptyHREFError"));
  274.     return false;
  275.   }
  276.   if (gDialog.linkTextInput)
  277.   {
  278.     // The text we will insert isn't really an attribute,
  279.     //  but it makes sense to validate it
  280.     newLinkText = TrimString(gDialog.linkTextInput.value);
  281.     if (!newLinkText)
  282.     {
  283.       if (href)
  284.         newLinkText = href
  285.       else
  286.       {
  287.         ShowInputErrorMessage(GetString("EmptyLinkTextError"));
  288.         SetTextboxFocus(gDialog.linkTextInput);
  289.         return false;
  290.       }
  291.     }
  292.   }
  293.   return true;
  294. }
  295.  
  296. function doHelpButton()
  297. {
  298.   openHelp("link_properties");
  299.   return true;
  300. }
  301.  
  302. function onAccept()
  303. {
  304.   if (ValidateData())
  305.   {
  306.     if (href.length > 0)
  307.     {
  308.       // Copy attributes to element we are changing or inserting
  309.       gActiveEditor.cloneAttributes(anchorElement, globalElement);
  310.  
  311.       // Coalesce into one undo transaction
  312.       gActiveEditor.beginTransaction();
  313.  
  314.       // Get text to use for a new link
  315.       if (insertLinkAtCaret)
  316.       {
  317.         // Append the link text as the last child node 
  318.         //   of the anchor node
  319.         var textNode = gActiveEditor.document.createTextNode(newLinkText);
  320.         if (textNode)
  321.           anchorElement.appendChild(textNode);
  322.         try {
  323.           gActiveEditor.insertElementAtSelection(anchorElement, false);
  324.         } catch (e) {
  325.           dump("Exception occured in InsertElementAtSelection\n");
  326.           return true;
  327.         }
  328.       } else if (insertNew || replaceExistingLink)
  329.       {
  330.         //  Link source was supplied by the selection,
  331.         //  so insert a link node as parent of this
  332.         //  (may be text, image, or other inline content)
  333.         try {
  334.           gActiveEditor.insertLinkAroundSelection(anchorElement);
  335.         } catch (e) {
  336.           dump("Exception occured in InsertElementAtSelection\n");
  337.           return true;
  338.         }
  339.       }
  340.       // Check if the link was to a heading 
  341.       if (href in gHNodeArray)
  342.       {
  343.         var anchorNode = gActiveEditor.createElementWithDefaults("a");
  344.         if (anchorNode)
  345.         {
  346.           anchorNode.name = href.substr(1);
  347.  
  348.           // Insert the anchor into the document, 
  349.           //  but don't let the transaction change the selection
  350.           gActiveEditor.setShouldTxnSetSelection(false);
  351.           gActiveEditor.insertNode(anchorNode, gHNodeArray[href], 0);
  352.           gActiveEditor.setShouldTxnSetSelection(true);
  353.         }
  354.       }
  355.       gActiveEditor.endTransaction();
  356.     } 
  357.     else if (!insertNew)
  358.     {
  359.       // We already had a link, but empty HREF means remove it
  360.       EditorRemoveTextProperty("href", "");
  361.     }
  362.     SaveWindowLocation();
  363.     return true;
  364.   }
  365.   return false;
  366. }
  367.