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