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 / EdConvertToTable.js < prev    next >
Text File  |  2003-06-08  |  10KB  |  354 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.  */
  23.  
  24. var gIndex;
  25. var gCommaIndex = "0";
  26. var gSpaceIndex = "1";
  27. var gOtherIndex = "2";
  28.  
  29. // dialog initialization code
  30. function Startup()
  31. {
  32.   if (!GetCurrentEditor())
  33.   {
  34.     window.close();
  35.     return;
  36.   }
  37.  
  38.   gDialog.sepRadioGroup      = document.getElementById("SepRadioGroup");
  39.   gDialog.sepCharacterInput  = document.getElementById("SepCharacterInput");
  40.   gDialog.deleteSepCharacter = document.getElementById("DeleteSepCharacter");
  41.   gDialog.collapseSpaces     = document.getElementById("CollapseSpaces");
  42.  
  43.   // We persist the user's separator character
  44.   gDialog.sepCharacterInput.value = gDialog.sepRadioGroup.getAttribute("character");
  45.  
  46.   gIndex = gDialog.sepRadioGroup.getAttribute("index");
  47.  
  48.   switch (gIndex)
  49.   {
  50.     case gCommaIndex:
  51.     default:
  52.       gDialog.sepRadioGroup.selectedItem = document.getElementById("comma");
  53.       break;
  54.     case gSpaceIndex:
  55.       gDialog.sepRadioGroup.selectedItem = document.getElementById("space");
  56.       break;
  57.     case gOtherIndex:
  58.       gDialog.sepRadioGroup.selectedItem = document.getElementById("other");
  59.       break;
  60.   }
  61.  
  62.   // Set initial enable state on character input and "collapse" checkbox
  63.   SelectCharacter(gIndex);
  64.  
  65.   SetTextboxFocus(gDialog.sepRadioGroup);
  66.  
  67.   SetWindowLocation();
  68. }
  69.  
  70. function InputSepCharacter()
  71. {
  72.   var str = gDialog.sepCharacterInput.value;
  73.  
  74.   // Limit input to 1 character
  75.   if (str.length > 1)
  76.     str = str.slice(0,1);
  77.  
  78.   // We can never allow tag or entity delimiters for separator character
  79.   if (str == "<" || str == ">" || str == "&" || str == ";" || str == " ")
  80.     str = "";
  81.  
  82.   gDialog.sepCharacterInput.value = str;
  83. }
  84.  
  85. function SelectCharacter(radioGroupIndex)
  86. {
  87.   gIndex = radioGroupIndex;
  88.   SetElementEnabledById("SepCharacterInput", gIndex == gOtherIndex);
  89.   SetElementEnabledById("CollapseSpaces", gIndex == gSpaceIndex);
  90. }
  91.  
  92. function onAccept()
  93. {
  94.   var sepCharacter = "";
  95.   switch ( gIndex )
  96.   {
  97.     case gCommaIndex:
  98.       sepCharacter = ",";
  99.       break;
  100.     case gSpaceIndex:
  101.       sepCharacter = " ";
  102.       break;
  103.     case gOtherIndex:
  104.       sepCharacter = gDialog.sepCharacterInput.value.slice(0,1);
  105.       break;
  106.   }
  107.  
  108.   var editor = GetCurrentEditor();
  109.   var str;
  110.   try {
  111.     // 1 = OutputSelectionOnly, 1024 = OutputLFLineBreak
  112.     str = editor.outputToString("text/html", 1+1024);
  113.   } catch (e) {}
  114.   if (!str)
  115.   {
  116.     SaveWindowLocation();
  117.     return true;
  118.   }
  119.  
  120.   // Replace nbsp with spaces:
  121.   str = str.replace(/\u00a0/g, " ");
  122.  
  123.   // Strip out </p> completely
  124.   str = str.replace(/\s*<\/p>\s*/g, "");
  125.  
  126.   // Trim whitespace adjacent to <p> and <br> tags
  127.   //  and replace <p> with <br> 
  128.   //  (which will be replaced with </tr> below)
  129.   str = str.replace(/\s*<p>\s*|\s*<br>\s*/g, "<br>");
  130.  
  131.   // Trim leading <br>s
  132.   str = str.replace(/^(<br>)+/, "");
  133.  
  134.   // Trim trailing <br>s
  135.   str = str.replace(/(<br>)+$/, "");
  136.  
  137.   // Reduce multiple internal <br> to just 1
  138.   // TODO: Maybe add a checkbox to let user decide
  139.   //str = str.replace(/(<br>)+/g, "<br>");
  140.  
  141.   // Trim leading and trailing spaces
  142.   str = str.replace(/^\s+|\s+$/, "");
  143.  
  144.   // Remove all tag contents so we don't replace
  145.   //   separator character within tags
  146.   // Also converts lists to something usefull
  147.   var stack = [];
  148.   var start;
  149.   var end;
  150.   var searchStart = 0;
  151.   var listSeparator = "";
  152.   var listItemSeparator = "";
  153.   var endList = false;
  154.  
  155.   do {
  156.     start = str.indexOf("<", searchStart);
  157.  
  158.     if (start >= 0)
  159.     {
  160.       end = str.indexOf(">", start+1);
  161.       if (end > start)
  162.       {
  163.         var tagContent = TrimString(str.slice(start+1, end));
  164.  
  165.         if ( /^ol|^ul|^dl/.test(tagContent) )
  166.         {
  167.           //  Replace list tag with <BR> to start new row 
  168.           //   at begining of second or greater list tag
  169.           str = str.slice(0, start) + listSeparator + str.slice(end+1);
  170.           if (listSeparator == "")
  171.             listSeparator = "<br>";
  172.           
  173.           // Reset for list item separation into cells
  174.           listItemSeparator = "";
  175.         }
  176.         else if ( /^li|^dt|^dd/.test(tagContent) )
  177.         {
  178.           // Start a new row if this is first item after the ending the last list
  179.           if (endList)
  180.             listItemSeparator = "<br>";
  181.  
  182.           // Start new cell at begining of second or greater list items
  183.           str = str.slice(0, start) + listItemSeparator + str.slice(end+1);
  184.  
  185.           if (endList || listItemSeparator == "")
  186.             listItemSeparator = sepCharacter;
  187.  
  188.           endList = false;
  189.         }
  190.         else 
  191.         {
  192.           // Find end tags
  193.           endList = /^\/ol|^\/ul|^\/dl/.test(tagContent);
  194.           if ( endList || /^\/li|^\/dt|^\/dd/.test(tagContent) )
  195.           {
  196.             // Strip out tag
  197.             str = str.slice(0, start) + str.slice(end+1);
  198.           }
  199.           else
  200.           {
  201.             // Not a list-related tag: Store tag contents in an array
  202.             stack.push(tagContent);
  203.            
  204.             // Keep the "<" and ">" while removing from source string
  205.             start++;
  206.             str = str.slice(0, start) + str.slice(end);
  207.           }
  208.         }
  209.       }
  210.       searchStart = start + 1;
  211.     }
  212.   } while (start >= 0);
  213.  
  214.   // Replace separator characters with table cells
  215.   var replaceString;
  216.   if (gDialog.deleteSepCharacter.checked)
  217.   {
  218.     replaceString = "";
  219.   }  
  220.   else
  221.   {
  222.     // Don't delete separator character,
  223.     //  so include it at start of string to replace
  224.     replaceString = sepCharacter;
  225.   }
  226.  
  227.   replaceString += "<td>"; 
  228.  
  229.   if (sepCharacter.length > 0)
  230.   {
  231.     var tempStr = sepCharacter;
  232.     var regExpChars = ".!@#$%^&*-+[]{}()\|\\\/";
  233.     if (regExpChars.indexOf(sepCharacter) >= 0)
  234.       tempStr = "\\" + sepCharacter;
  235.  
  236.     if (gIndex == gSpaceIndex)
  237.     {
  238.       // If checkbox is checked, 
  239.       //   one or more adjacent spaces are one separator
  240.       if (gDialog.collapseSpaces.checked)
  241.           tempStr = "\\s+"
  242.         else
  243.           tempStr = "\\s";
  244.     }
  245.     var pattern = new RegExp(tempStr, "g");
  246.     str = str.replace(pattern, replaceString);
  247.   }
  248.  
  249.   // Put back tag contents that we removed above
  250.   searchStart = 0;
  251.   var stackIndex = 0;
  252.   do {
  253.     start = str.indexOf("<", searchStart);
  254.     end = start + 1;
  255.     if (start >= 0 && str.charAt(end) == ">")
  256.     {
  257.       // We really need a FIFO stack!
  258.       str = str.slice(0, end) + stack[stackIndex++] + str.slice(end);
  259.     }
  260.     searchStart = end;
  261.  
  262.   } while (start >= 0);
  263.  
  264.   // End table row and start another for each br or p
  265.   str = str.replace(/\s*<br>\s*/g, "</tr>\n<tr><td>");
  266.  
  267.   // Add the table tags and the opening and closing tr/td tags
  268.   // Default table attributes should be same as those used in nsHTMLEditor::CreateElementWithDefaults()
  269.   // (Default width="100%" is used in EdInsertTable.js)
  270.   str = "<table border=\"1\" width=\"100%\" cellpadding=\"2\" cellspacing=\"2\">\n<tr><td>" + str + "</tr>\n</table>\n";
  271.  
  272.   editor.beginTransaction();
  273.   
  274.   // Delete the selection -- makes it easier to find where table will insert
  275.   var nodeBeforeTable = null;
  276.   var nodeAfterTable = null;
  277.   try {
  278.     editor.deleteSelection(0);
  279.  
  280.     var anchorNodeBeforeInsert = editor.selection.anchorNode;
  281.     var offset = editor.selection.anchorOffset;
  282.     if (anchorNodeBeforeInsert.nodeType == Node.TEXT_NODE)
  283.     {
  284.       // Text was split. Table should be right after the first or before 
  285.       nodeBeforeTable = anchorNodeBeforeInsert.previousSibling;
  286.       nodeAfterTable = anchorNodeBeforeInsert;
  287.     }
  288.     else
  289.     {
  290.       // Table should be inserted right after node pointed to by selection
  291.       if (offset > 0)
  292.         nodeBeforeTable = anchorNodeBeforeInsert.childNodes.item(offset - 1);
  293.  
  294.       nodeAfterTable = anchorNodeBeforeInsert.childNodes.item(offset);
  295.     }
  296.   
  297.     editor.insertHTML(str);
  298.   } catch (e) {}
  299.  
  300.   var table = null;
  301.   if (nodeAfterTable)
  302.   {
  303.     var previous = nodeAfterTable.previousSibling;
  304.     if (previous && previous.nodeName.toLowerCase() == "table")
  305.       table = previous;
  306.   }
  307.   if (!table && nodeBeforeTable)
  308.   {
  309.     var next = nodeBeforeTable.nextSibling;
  310.     if (next && next.nodeName.toLowerCase() == "table")
  311.       table = next;
  312.   }
  313.  
  314.   if (table)
  315.   {
  316.     // Fixup table only if pref is set
  317.     var prefs = GetPrefs();
  318.     var firstRow;
  319.     try {
  320.       if (prefs && prefs.getBoolPref("editor.table.maintain_structure") )
  321.         editor.normalizeTable(table);
  322.  
  323.       firstRow = editor.getFirstRow(table);
  324.     } catch(e) {}
  325.  
  326.     // Put caret in first cell
  327.     if (firstRow)
  328.     {
  329.       var node2 = firstRow.firstChild;
  330.       do {
  331.         if (node2.nodeName.toLowerCase() == "td" ||
  332.             node2.nodeName.toLowerCase() == "th")
  333.         {
  334.           try { 
  335.             editor.selection.collapse(node2, 0);
  336.           } catch(e) {}
  337.           break;
  338.         }
  339.         node2 = node.nextSibling;
  340.       } while (node2);
  341.     }
  342.   }
  343.  
  344.   editor.endTransaction();
  345.  
  346.   // Save persisted attributes
  347.   gDialog.sepRadioGroup.setAttribute("index", gIndex);
  348.   if (gIndex == gOtherIndex)
  349.     gDialog.sepRadioGroup.setAttribute("character", sepCharacter);
  350.  
  351.   SaveWindowLocation();
  352.   return true;
  353. }
  354.