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