Revision control
Copy as Markdown
Other Tools
/* 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
/* import-globals-from ../../composer/content/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.setAttribute("label", 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();
}