!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 * Ryan Cassin (rcassin@supernova.org)
25 * David Turley (dturley@pobox.com) contributed Roman Numeral conversion code.
26 * Neil Rashbrook <neil@parkwaycc.co.uk>
27 *
28 * Alternatively, the contents of this file may be used under the terms of
29 * either of the GNU General Public License Version 2 or later (the "GPL"),
30 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
39 *
40 * ***** END LICENSE BLOCK ***** */
41
42 //Cancel() is in EdDialogCommon.js
43 var gBulletStyleType = "";
44 var gNumberStyleType = "";
45 var gListElement;
46 var gOriginalListType = "";
47 var gListType = "";
48 var gMixedListSelection = false;
49 var gStyleType = "";
50 var gOriginalStyleType = "";
51 const gOnesArray = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
52 const gTensArray = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"];
53 const gHundredsArray = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"];
54 const gThousandsArray = ["", "M", "MM", "MMM", "MMMM", "MMMMM", "MMMMMM", "MMMMMMM", "MMMMMMMM", "MMMMMMMMM"];
55 const gRomanDigits = {I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000};
56 const A = "A".charCodeAt(0);
57 const gArabic = "1";
58 const gUpperRoman = "I";
59 const gLowerRoman = "i";
60 const gUpperLetters = "A";
61 const gLowerLetters = "a";
62 const gDecimalCSS = "decimal";
63 const gUpperRomanCSS = "upper-roman";
64 const gLowerRomanCSS = "lower-roman";
65 const gUpperAlphaCSS = "upper-alpha";
66 const gLowerAlphaCSS = "lower-alpha";
67
68 // dialog initialization code
Startup
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
69 function Startup()
70 {
71 var editor = GetCurrentEditor();
72 if (!editor)
73 {
74 window.close();
75 return;
76 }
77 gDialog.ListTypeList = document.getElementById("ListType");
78 gDialog.BulletStyleList = document.getElementById("BulletStyle");
79 gDialog.BulletStyleLabel = document.getElementById("BulletStyleLabel");
80 gDialog.StartingNumberInput = document.getElementById("StartingNumber");
81 gDialog.StartingNumberLabel = document.getElementById("StartingNumberLabel");
82 gDialog.AdvancedEditButton = document.getElementById("AdvancedEditButton1");
83 gDialog.RadioGroup = document.getElementById("RadioGroup");
84 gDialog.ChangeAllRadio = document.getElementById("ChangeAll");
85 gDialog.ChangeSelectedRadio = document.getElementById("ChangeSelected");
86
87 // Try to get an existing list(s)
88 var mixedObj = { value: null };
89 try {
90 gListType = editor.getListState(mixedObj, {}, {}, {} );
91
92 // We may have mixed list and non-list, or > 1 list type in selection
93 gMixedListSelection = mixedObj.value;
94
95 // Get the list element at the anchor node
96 gListElement = editor.getElementOrParentByTagName("list", null);
97 } catch (e) {}
98
99 // The copy to use in AdvancedEdit
100 if (gListElement)
101 globalElement = gListElement.cloneNode(false);
102
103 // Show extra options for changing entire list if we have one already.
104 gDialog.RadioGroup.collapsed = !gListElement;
105 if (gListElement)
106 {
107 // Radio button index is persistent
108 if (gDialog.RadioGroup.getAttribute("index") == "1")
109 gDialog.RadioGroup.selectedItem = gDialog.ChangeSelectedRadio;
110 else
111 gDialog.RadioGroup.selectedItem = gDialog.ChangeAllRadio;
112 }
113
114 InitDialog();
115
116 gOriginalListType = gListType;
117
118 gDialog.ListTypeList.focus();
119
120 SetWindowLocation();
121 }
122
InitDialog
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
123 function InitDialog()
124 {
125 // Note that if mixed, we we pay attention
126 // only to the anchor node's list type
127 // (i.e., don't confuse user with "mixed" designation)
128 if (gListElement)
129 gListType = gListElement.nodeName.toLowerCase();
130 else
131 gListType = "";
132
133 gDialog.ListTypeList.value = gListType;
134 gDialog.StartingNumberInput.value = "";
135
136 // Last param = true means attribute value is case-sensitive
137 var type = globalElement ? GetHTMLOrCSSStyleValue(globalElement, "type", "list-style-type") : null;
138
139 var index = 0;
140 if (gListType == "ul")
141 {
142 if (type)
143 {
144 type = type.toLowerCase();
145 gBulletStyleType = type;
146 gOriginalStyleType = type;
147 }
148 }
149 else if (gListType == "ol")
150 {
151 // Translate CSS property strings
152 switch (type.toLowerCase())
153 {
154 case gDecimalCSS:
155 type = gArabic;
156 break;
157 case gUpperRomanCSS:
158 type = gUpperRoman;
159 break;
160 case gLowerRomanCSS:
161 type = gLowerRoman;
162 break;
163 case gUpperAlphaCSS:
164 type = gUpperLetters;
165 break;
166 case gLowerAlphaCSS:
167 type = gLowerLetters;
168 break;
169 }
170 if (type)
171 {
172 gNumberStyleType = type;
173 gOriginalStyleType = type;
174 }
175
176 // Convert attribute number to appropriate letter or roman numeral
177 gDialog.StartingNumberInput.value =
178 ConvertStartAttrToUserString(globalElement.getAttribute("start"), type);
179 }
180 BuildBulletStyleList();
181 }
182
183 // Convert attribute number to appropriate letter or roman numeral
ConvertStartAttrToUserString
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
184 function ConvertStartAttrToUserString(startAttr, type)
185 {
186 switch (type)
187 {
188 case gUpperRoman:
189 startAttr = ConvertArabicToRoman(startAttr);
190 break;
191 case gLowerRoman:
192 startAttr = ConvertArabicToRoman(startAttr).toLowerCase();
193 break;
194 case gUpperLetters:
195 startAttr = ConvertArabicToLetters(startAttr);
196 break;
197 case gLowerLetters:
198 startAttr = ConvertArabicToLetters(startAttr).toLowerCase();
199 break;
200 }
201 return startAttr;
202 }
203
BuildBulletStyleList
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
204 function BuildBulletStyleList()
205 {
206 gDialog.BulletStyleList.removeAllItems();
207 var label;
208
209 if (gListType == "ul")
210 {
211 gDialog.BulletStyleList.removeAttribute("disabled");
212 gDialog.BulletStyleLabel.removeAttribute("disabled");
213 gDialog.StartingNumberInput.setAttribute("disabled", "true");
214 gDialog.StartingNumberLabel.setAttribute("disabled", "true");
215
216 label = GetString("BulletStyle");
217
218 gDialog.BulletStyleList.appendItem(GetString("Automatic"), "");
219 gDialog.BulletStyleList.appendItem(GetString("SolidCircle"), "disc");
220 gDialog.BulletStyleList.appendItem(GetString("OpenCircle"), "circle");
221 gDialog.BulletStyleList.appendItem(GetString("SolidSquare"), "square");
222
223 gDialog.BulletStyleList.value = gBulletStyleType;
224 }
225 else if (gListType == "ol")
226 {
227 gDialog.BulletStyleList.removeAttribute("disabled");
228 gDialog.BulletStyleLabel.removeAttribute("disabled");
229 gDialog.StartingNumberInput.removeAttribute("disabled");
230 gDialog.StartingNumberLabel.removeAttribute("disabled");
231 label = GetString("NumberStyle");
232
233 gDialog.BulletStyleList.appendItem(GetString("Automatic"), "");
234 gDialog.BulletStyleList.appendItem(GetString("Style_1"), gArabic);
235 gDialog.BulletStyleList.appendItem(GetString("Style_I"), gUpperRoman);
236 gDialog.BulletStyleList.appendItem(GetString("Style_i"), gLowerRoman);
237 gDialog.BulletStyleList.appendItem(GetString("Style_A"), gUpperLetters);
238 gDialog.BulletStyleList.appendItem(GetString("Style_a"), gLowerLetters);
239
240 gDialog.BulletStyleList.value = gNumberStyleType;
241 }
242 else
243 {
244 gDialog.BulletStyleList.setAttribute("disabled", "true");
245 gDialog.BulletStyleLabel.setAttribute("disabled", "true");
246 gDialog.StartingNumberInput.setAttribute("disabled", "true");
247 gDialog.StartingNumberLabel.setAttribute("disabled", "true");
248 }
249
250 // Disable advanced edit button if changing to "normal"
251 if (gListType)
252 gDialog.AdvancedEditButton.removeAttribute("disabled");
253 else
254 gDialog.AdvancedEditButton.setAttribute("disabled", "true");
255
256 if (label)
257 gDialog.BulletStyleLabel.setAttribute("label",label);
258 }
259
SelectListType
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
260 function SelectListType()
261 {
262 // Each list type is stored in the "value" of each menuitem
263 var NewType = gDialog.ListTypeList.value;
264
265 if (NewType == "ol")
266 SetTextboxFocus(gDialog.StartingNumberInput);
267
268 if (gListType != NewType)
269 {
270 gListType = NewType;
271
272 // Create a newlist object for Advanced Editing
273 try {
274 if (gListType)
275 globalElement = GetCurrentEditor().createElementWithDefaults(gListType);
276 } catch (e) {}
277
278 BuildBulletStyleList();
279 }
280 }
281
SelectBulletStyle
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
282 function SelectBulletStyle()
283 {
284 // Save the selected index so when user changes
285 // list style, restore index to associated list
286 // Each bullet or number type is stored in the "value" of each menuitem
287 if (gListType == "ul")
288 gBulletStyleType = gDialog.BulletStyleList.value;
289 else if (gListType == "ol")
290 {
291 var type = gDialog.BulletStyleList.value;
292 if (gNumberStyleType != type)
293 {
294 // Convert existing input value to attr number first,
295 // then convert to the appropriate format for the newly-selected
296 gDialog.StartingNumberInput.value =
297 ConvertStartAttrToUserString( ConvertUserStringToStartAttr(gNumberStyleType), type);
298
299 gNumberStyleType = type;
300 SetTextboxFocus(gDialog.StartingNumberInput);
301 }
302 }
303 }
304
ValidateData
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
305 function ValidateData()
306 {
307 gBulletStyleType = gDialog.BulletStyleList.value;
308 // globalElement should already be of the correct type
309
310 if (globalElement)
311 {
312 var editor = GetCurrentEditor();
313 if (gListType == "ul")
314 {
315 if (gBulletStyleType && gDialog.ChangeAllRadio.selected)
316 globalElement.setAttribute("type", gBulletStyleType);
317 else
318 try {
319 editor.removeAttributeOrEquivalent(globalElement, "type", true);
320 } catch (e) {}
321
322 }
323 else if (gListType == "ol")
324 {
325 if (gBulletStyleType)
326 globalElement.setAttribute("type", gBulletStyleType);
327 else
328 try {
329 editor.removeAttributeOrEquivalent(globalElement, "type", true);
330 } catch (e) {}
331
332 var startingNumber = ConvertUserStringToStartAttr(gBulletStyleType);
333 if (startingNumber)
334 globalElement.setAttribute("start", startingNumber);
335 else
336 globalElement.removeAttribute("start");
337 }
338 }
339 return true;
340 }
341
ConvertUserStringToStartAttr
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
342 function ConvertUserStringToStartAttr(type)
343 {
344 var startingNumber = TrimString(gDialog.StartingNumberInput.value);
345
346 switch (type)
347 {
348 case gUpperRoman:
349 case gLowerRoman:
350 // If the input isn't an integer, assume it's a roman numeral. Convert it.
351 if (!Number(startingNumber))
352 startingNumber = ConvertRomanToArabic(startingNumber);
353 break;
354 case gUpperLetters:
355 case gLowerLetters:
356 // Get the number equivalent of the letters
357 if (!Number(startingNumber))
358 startingNumber = ConvertLettersToArabic(startingNumber);
359 break;
360 }
361 return startingNumber;
362 }
363
ConvertRomanToArabic
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
364 function ConvertRomanToArabic(num)
365 {
366 num = num.toUpperCase();
367 if (num && !/[^MDCLXVI]/i.test(num))
368 {
369 var Arabic = 0;
370 var last_digit = 1000;
371 for (var i=0; i < num.length; i++)
372 {
373 var digit = gRomanDigits[num.charAt(i)];
374 if (last_digit < digit)
375 Arabic -= 2 * last_digit;
376
377 last_digit = digit;
378 Arabic += last_digit;
379 }
380 return Arabic;
381 }
382
383 return "";
384 }
385
ConvertArabicToRoman
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
386 function ConvertArabicToRoman(num)
387 {
388 if (/^\d{1,4}$/.test(num))
389 {
390 var digits = ("000" + num).substr(-4);
391 return gThousandsArray[digits.charAt(0)] +
392 gHundredsArray[digits.charAt(1)] +
393 gTensArray[digits.charAt(2)] +
394 gOnesArray[digits.charAt(3)];
395 }
396 return "";
397 }
398
ConvertLettersToArabic
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
399 function ConvertLettersToArabic(letters)
400 {
401 letters = letters.toUpperCase();
402 if (!letters || /[^A-Z]/.test(letters))
403 return "";
404
405 var num = 0;
406 for (var i = 0; i < letters.length; i++)
407 num = num * 26 + letters.charCodeAt(i) - A + 1;
408 return num;
409 }
410
ConvertArabicToLetters
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
411 function ConvertArabicToLetters(num)
412 {
413 var letters = "";
414 while (num) {
415 num--;
416 letters = String.fromCharCode(A + (num % 26)) + letters;
417 num = Math.floor(num / 26);
418 }
419 return letters;
420 }
421
onAccept
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
422 function onAccept()
423 {
424 if (ValidateData())
425 {
426 // Coalesce into one undo transaction
427 var editor = GetCurrentEditor();
428
429 editor.beginTransaction();
430
431 var changeEntireList = gDialog.RadioGroup.selectedItem == gDialog.ChangeAllRadio;
432
433 // Remember which radio button was selected
434 if (gListElement)
435 gDialog.RadioGroup.setAttribute("index", changeEntireList ? "0" : "1");
436
437 var changeList;
438 if (gListElement && gDialog.ChangeAllRadio.selected)
439 {
440 changeList = true;
441 }
442 else
443 changeList = gMixedListSelection || gListType != gOriginalListType ||
444 gBulletStyleType != gOriginalStyleType;
445 if (changeList)
446 {
447 try {
448 if (gListType)
449 {
450 editor.makeOrChangeList(gListType, changeEntireList,
451 (gBulletStyleType != gOriginalStyleType) ? gBulletStyleType : null);
452
453 // Get the new list created:
454 gListElement = editor.getElementOrParentByTagName(gListType, null);
455
456 editor.cloneAttributes(gListElement, globalElement);
457 }
458 else
459 {
460 // Remove all existing lists
461 if (gListElement && changeEntireList)
462 editor.selectElement(gListElement);
463
464 editor.removeList("ol");
465 editor.removeList("ul");
466 editor.removeList("dl");
467 }
468 } catch (e) {}
469 }
470
471 editor.endTransaction();
472
473 SaveWindowLocation();
474
475 return true;
476 }
477 return false;
478 }