/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* import-globals-from ../editorUtilities.js */ /* import-globals-from EdDialogCommon.js */ // Cancel() is in EdDialogCommon.js var gBulletStyleType = ""; var gNumberStyleType = ""; var gListElement; var gOriginalListType = ""; var gListType = ""; var gMixedListSelection = false; var gStyleType = ""; var gOriginalStyleType = ""; const gOnesArray = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"]; const gTensArray = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"]; const gHundredsArray = [ "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", ]; const gThousandsArray = [ "", "M", "MM", "MMM", "MMMM", "MMMMM", "MMMMMM", "MMMMMMM", "MMMMMMMM", "MMMMMMMMM", ]; const gRomanDigits = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 }; const A = "A".charCodeAt(0); const gArabic = "1"; const gUpperRoman = "I"; const gLowerRoman = "i"; const gUpperLetters = "A"; const gLowerLetters = "a"; const gDecimalCSS = "decimal"; const gUpperRomanCSS = "upper-roman"; const gLowerRomanCSS = "lower-roman"; const gUpperAlphaCSS = "upper-alpha"; const gLowerAlphaCSS = "lower-alpha"; // dialog initialization code document.addEventListener("dialogaccept", onAccept); document.addEventListener("dialogcancel", onCancel); function Startup() { var editor = GetCurrentEditor(); if (!editor) { window.close(); return; } gDialog.ListTypeList = document.getElementById("ListType"); gDialog.BulletStyleList = document.getElementById("BulletStyle"); gDialog.BulletStyleLabel = document.getElementById("BulletStyleLabel"); gDialog.StartingNumberInput = document.getElementById("StartingNumber"); gDialog.StartingNumberLabel = document.getElementById("StartingNumberLabel"); gDialog.AdvancedEditButton = document.getElementById("AdvancedEditButton1"); gDialog.RadioGroup = document.getElementById("RadioGroup"); gDialog.ChangeAllRadio = document.getElementById("ChangeAll"); gDialog.ChangeSelectedRadio = document.getElementById("ChangeSelected"); // Try to get an existing list(s) var mixedObj = { value: null }; try { gListType = editor.getListState(mixedObj, {}, {}, {}); // We may have mixed list and non-list, or > 1 list type in selection gMixedListSelection = mixedObj.value; // Get the list element at the anchor node gListElement = editor.getElementOrParentByTagName("list", null); } catch (e) {} // The copy to use in AdvancedEdit if (gListElement) { globalElement = gListElement.cloneNode(false); } // Show extra options for changing entire list if we have one already. gDialog.RadioGroup.collapsed = !gListElement; if (gListElement) { // Radio button index is persistent if (gDialog.RadioGroup.getAttribute("index") == "1") { gDialog.RadioGroup.selectedItem = gDialog.ChangeSelectedRadio; } else { gDialog.RadioGroup.selectedItem = gDialog.ChangeAllRadio; } } InitDialog(); gOriginalListType = gListType; gDialog.ListTypeList.focus(); SetWindowLocation(); } function InitDialog() { // Note that if mixed, we we pay attention // only to the anchor node's list type // (i.e., don't confuse user with "mixed" designation) if (gListElement) { gListType = gListElement.nodeName.toLowerCase(); } else { gListType = ""; } gDialog.ListTypeList.value = gListType; gDialog.StartingNumberInput.value = ""; // Last param = true means attribute value is case-sensitive var type = globalElement ? GetHTMLOrCSSStyleValue(globalElement, "type", "list-style-type") : null; if (gListType == "ul") { if (type) { type = type.toLowerCase(); gBulletStyleType = type; gOriginalStyleType = type; } } else if (gListType == "ol") { // Translate CSS property strings switch (type.toLowerCase()) { case gDecimalCSS: type = gArabic; break; case gUpperRomanCSS: type = gUpperRoman; break; case gLowerRomanCSS: type = gLowerRoman; break; case gUpperAlphaCSS: type = gUpperLetters; break; case gLowerAlphaCSS: type = gLowerLetters; break; } if (type) { gNumberStyleType = type; gOriginalStyleType = type; } // Convert attribute number to appropriate letter or roman numeral gDialog.StartingNumberInput.value = ConvertStartAttrToUserString( globalElement.getAttribute("start"), type ); } BuildBulletStyleList(); } // Convert attribute number to appropriate letter or roman numeral function ConvertStartAttrToUserString(startAttr, type) { switch (type) { case gUpperRoman: startAttr = ConvertArabicToRoman(startAttr); break; case gLowerRoman: startAttr = ConvertArabicToRoman(startAttr).toLowerCase(); break; case gUpperLetters: startAttr = ConvertArabicToLetters(startAttr); break; case gLowerLetters: startAttr = ConvertArabicToLetters(startAttr).toLowerCase(); break; } return startAttr; } function BuildBulletStyleList() { gDialog.BulletStyleList.removeAllItems(); var label; if (gListType == "ul") { gDialog.BulletStyleList.removeAttribute("disabled"); gDialog.BulletStyleLabel.removeAttribute("disabled"); gDialog.StartingNumberInput.setAttribute("disabled", "true"); gDialog.StartingNumberLabel.setAttribute("disabled", "true"); label = GetString("BulletStyle"); gDialog.BulletStyleList.appendItem(GetString("Automatic"), ""); gDialog.BulletStyleList.appendItem(GetString("SolidCircle"), "disc"); gDialog.BulletStyleList.appendItem(GetString("OpenCircle"), "circle"); gDialog.BulletStyleList.appendItem(GetString("SolidSquare"), "square"); gDialog.BulletStyleList.value = gBulletStyleType; } else if (gListType == "ol") { gDialog.BulletStyleList.removeAttribute("disabled"); gDialog.BulletStyleLabel.removeAttribute("disabled"); gDialog.StartingNumberInput.removeAttribute("disabled"); gDialog.StartingNumberLabel.removeAttribute("disabled"); label = GetString("NumberStyle"); gDialog.BulletStyleList.appendItem(GetString("Automatic"), ""); gDialog.BulletStyleList.appendItem(GetString("Style_1"), gArabic); gDialog.BulletStyleList.appendItem(GetString("Style_I"), gUpperRoman); gDialog.BulletStyleList.appendItem(GetString("Style_i"), gLowerRoman); gDialog.BulletStyleList.appendItem(GetString("Style_A"), gUpperLetters); gDialog.BulletStyleList.appendItem(GetString("Style_a"), gLowerLetters); gDialog.BulletStyleList.value = gNumberStyleType; } else { gDialog.BulletStyleList.setAttribute("disabled", "true"); gDialog.BulletStyleLabel.setAttribute("disabled", "true"); gDialog.StartingNumberInput.setAttribute("disabled", "true"); gDialog.StartingNumberLabel.setAttribute("disabled", "true"); } // Disable advanced edit button if changing to "normal" if (gListType) { gDialog.AdvancedEditButton.removeAttribute("disabled"); } else { gDialog.AdvancedEditButton.setAttribute("disabled", "true"); } if (label) { gDialog.BulletStyleLabel.textContent = label; } } function SelectListType() { // Each list type is stored in the "value" of each menuitem var NewType = gDialog.ListTypeList.value; if (NewType == "ol") { SetTextboxFocus(gDialog.StartingNumberInput); } if (gListType != NewType) { gListType = NewType; // Create a newlist object for Advanced Editing try { if (gListType) { globalElement = GetCurrentEditor().createElementWithDefaults(gListType); } } catch (e) {} BuildBulletStyleList(); } } function SelectBulletStyle() { // Save the selected index so when user changes // list style, restore index to associated list // Each bullet or number type is stored in the "value" of each menuitem if (gListType == "ul") { gBulletStyleType = gDialog.BulletStyleList.value; } else if (gListType == "ol") { var type = gDialog.BulletStyleList.value; if (gNumberStyleType != type) { // Convert existing input value to attr number first, // then convert to the appropriate format for the newly-selected gDialog.StartingNumberInput.value = ConvertStartAttrToUserString( ConvertUserStringToStartAttr(gNumberStyleType), type ); gNumberStyleType = type; SetTextboxFocus(gDialog.StartingNumberInput); } } } function ValidateData() { gBulletStyleType = gDialog.BulletStyleList.value; // globalElement should already be of the correct type if (globalElement) { var editor = GetCurrentEditor(); if (gListType == "ul") { if (gBulletStyleType && gDialog.ChangeAllRadio.selected) { globalElement.setAttribute("type", gBulletStyleType); } else { try { editor.removeAttributeOrEquivalent(globalElement, "type", true); } catch (e) {} } } else if (gListType == "ol") { if (gBulletStyleType) { globalElement.setAttribute("type", gBulletStyleType); } else { try { editor.removeAttributeOrEquivalent(globalElement, "type", true); } catch (e) {} } var startingNumber = ConvertUserStringToStartAttr(gBulletStyleType); if (startingNumber) { globalElement.setAttribute("start", startingNumber); } else { globalElement.removeAttribute("start"); } } } return true; } function ConvertUserStringToStartAttr(type) { var startingNumber = TrimString(gDialog.StartingNumberInput.value); switch (type) { case gUpperRoman: case gLowerRoman: // If the input isn't an integer, assume it's a roman numeral. Convert it. if (!Number(startingNumber)) { startingNumber = ConvertRomanToArabic(startingNumber); } break; case gUpperLetters: case gLowerLetters: // Get the number equivalent of the letters if (!Number(startingNumber)) { startingNumber = ConvertLettersToArabic(startingNumber); } break; } return startingNumber; } function ConvertRomanToArabic(num) { num = num.toUpperCase(); if (num && !/[^MDCLXVI]/i.test(num)) { var Arabic = 0; var last_digit = 1000; for (var i = 0; i < num.length; i++) { var digit = gRomanDigits[num.charAt(i)]; if (last_digit < digit) { Arabic -= 2 * last_digit; } last_digit = digit; Arabic += last_digit; } return Arabic; } return ""; } function ConvertArabicToRoman(num) { if (/^\d{1,4}$/.test(num)) { var digits = ("000" + num).substr(-4); return ( gThousandsArray[digits.charAt(0)] + gHundredsArray[digits.charAt(1)] + gTensArray[digits.charAt(2)] + gOnesArray[digits.charAt(3)] ); } return ""; } function ConvertLettersToArabic(letters) { letters = letters.toUpperCase(); if (!letters || /[^A-Z]/.test(letters)) { return ""; } var num = 0; for (var i = 0; i < letters.length; i++) { num = num * 26 + letters.charCodeAt(i) - A + 1; } return num; } function ConvertArabicToLetters(num) { var letters = ""; while (num) { num--; letters = String.fromCharCode(A + (num % 26)) + letters; num = Math.floor(num / 26); } return letters; } function onAccept(event) { if (ValidateData()) { // Coalesce into one undo transaction var editor = GetCurrentEditor(); editor.beginTransaction(); var changeEntireList = gDialog.RadioGroup.selectedItem == gDialog.ChangeAllRadio; // Remember which radio button was selected if (gListElement) { gDialog.RadioGroup.setAttribute("index", changeEntireList ? "0" : "1"); } var changeList; if (gListElement && gDialog.ChangeAllRadio.selected) { changeList = true; } else { changeList = gMixedListSelection || gListType != gOriginalListType || gBulletStyleType != gOriginalStyleType; } if (changeList) { try { if (gListType) { editor.makeOrChangeList( gListType, changeEntireList, gBulletStyleType != gOriginalStyleType ? gBulletStyleType : null ); // Get the new list created: gListElement = editor.getElementOrParentByTagName(gListType, null); editor.cloneAttributes(gListElement, globalElement); } else { // Remove all existing lists if (gListElement && changeEntireList) { editor.selectElement(gListElement); } editor.removeList("ol"); editor.removeList("ul"); editor.removeList("dl"); } } catch (e) {} } editor.endTransaction(); SaveWindowLocation(); return; } event.preventDefault(); }