diff options
Diffstat (limited to 'comm/mail/components/compose/content/dialogs/EdAEHTMLAttributes.js')
-rw-r--r-- | comm/mail/components/compose/content/dialogs/EdAEHTMLAttributes.js | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/comm/mail/components/compose/content/dialogs/EdAEHTMLAttributes.js b/comm/mail/components/compose/content/dialogs/EdAEHTMLAttributes.js new file mode 100644 index 0000000000..127bfb858b --- /dev/null +++ b/comm/mail/components/compose/content/dialogs/EdAEHTMLAttributes.js @@ -0,0 +1,362 @@ +/* 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 EdAdvancedEdit.js */ +/* import-globals-from EdDialogCommon.js */ + +function BuildHTMLAttributeNameList() { + gDialog.AddHTMLAttributeNameInput.removeAllItems(); + + var elementName = gElement.localName; + var attNames = gHTMLAttr[elementName]; + + if (attNames && attNames.length) { + var menuitem; + + for (var i = 0; i < attNames.length; i++) { + var name = attNames[i]; + + if (name == "_core") { + // Signal to append the common 'core' attributes. + for (var j = 0; j < gCoreHTMLAttr.length; j++) { + name = gCoreHTMLAttr[j]; + + // only filtering rule used for core attributes as of 8-20-01 + // Add more rules if necessary. + if (name.includes("^")) { + name = name.replace(/\^/g, ""); + menuitem = gDialog.AddHTMLAttributeNameInput.appendItem(name, name); + menuitem.setAttribute("limitFirstChar", "true"); + } else { + gDialog.AddHTMLAttributeNameInput.appendItem(name, name); + } + } + } else if (name == "-") { + // Signal for separator + var popup = gDialog.AddHTMLAttributeNameInput.menupopup; + if (popup) { + var sep = document.createXULElement("menuseparator"); + if (sep) { + popup.appendChild(sep); + } + } + } else { + // Get information about value filtering + let forceOneChar = name.includes("!"); + let forceInteger = name.includes("#"); + let forceSignedInteger = name.includes("+"); + let forceIntOrPercent = name.includes("%"); + let limitFirstChar = name.includes("^"); + // let required = name.includes("$"); + + // Strip flag characters + name = name.replace(/[!^#%$+]/g, ""); + + menuitem = gDialog.AddHTMLAttributeNameInput.appendItem(name, name); + if (menuitem) { + // Signify "required" attributes by special style + // TODO: Don't do this until next version, when we add + // explanatory text and an 'Autofill Required Attributes' button + // if (required) + // menuitem.setAttribute("class", "menuitem-highlight-1"); + + // Set flags to filter value input + if (forceOneChar) { + menuitem.setAttribute("forceOneChar", "true"); + } + if (limitFirstChar) { + menuitem.setAttribute("limitFirstChar", "true"); + } + if (forceInteger) { + menuitem.setAttribute("forceInteger", "true"); + } + if (forceSignedInteger) { + menuitem.setAttribute("forceSignedInteger", "true"); + } + if (forceIntOrPercent) { + menuitem.setAttribute("forceIntOrPercent", "true"); + } + } + } + } + } +} + +// build attribute list in tree form from element attributes +function BuildHTMLAttributeTable() { + var nodeMap = gElement.attributes; + var i; + if (nodeMap.length > 0) { + var added = false; + for (i = 0; i < nodeMap.length; i++) { + let name = nodeMap[i].name.trim().toLowerCase(); + if ( + CheckAttributeNameSimilarity(nodeMap[i].nodeName, HTMLAttrs) || + name.startsWith("on") || + name == "style" + ) { + continue; // repeated or non-HTML attribute, ignore this one and go to next + } + if ( + !name.startsWith("_moz") && + AddTreeItem(name, nodeMap[i].value, "HTMLAList", HTMLAttrs) + ) { + added = true; + } + } + + if (added) { + SelectHTMLTree(0); + } + } +} + +function ClearHTMLInputWidgets() { + gDialog.AddHTMLAttributeTree.view.selection.clearSelection(); + gDialog.AddHTMLAttributeNameInput.value = ""; + gDialog.AddHTMLAttributeValueInput.value = ""; + SetTextboxFocus(gDialog.AddHTMLAttributeNameInput); +} + +function onSelectHTMLTreeItem() { + if (!gDoOnSelectTree) { + return; + } + + var tree = gDialog.AddHTMLAttributeTree; + if (tree && tree.view.selection.count) { + var inputName = TrimString( + gDialog.AddHTMLAttributeNameInput.value + ).toLowerCase(); + var selectedItem = getSelectedItem(tree); + var selectedName = + selectedItem.firstElementChild.firstElementChild.getAttribute("label"); + + if (inputName == selectedName) { + // Already editing selected name - just update the value input + gDialog.AddHTMLAttributeValueInput.value = + GetTreeItemValueStr(selectedItem); + } else { + gDialog.AddHTMLAttributeNameInput.value = selectedName; + + // Change value input based on new selected name + onInputHTMLAttributeName(); + } + } +} + +function onInputHTMLAttributeName() { + let attName = gDialog.AddHTMLAttributeNameInput.value.toLowerCase().trim(); + + // Clear value widget, but prevent triggering update in tree + gUpdateTreeValue = false; + gDialog.AddHTMLAttributeValueInput.value = ""; + gUpdateTreeValue = true; + + if (attName) { + // Get value list for current attribute name + var valueListName; + + // Most elements have the "dir" attribute, + // so we have just one array for the allowed values instead + // requiring duplicate entries for each element in EdAEAttributes.js + if (attName == "dir") { + valueListName = "all_dir"; + } else { + valueListName = gElement.localName + "_" + attName; + } + + // Strip off leading "_" we sometimes use (when element name is reserved word) + if (valueListName.startsWith("_")) { + valueListName = valueListName.slice(1); + } + + let useMenulist = false; // Editable menulist vs. input for the value. + var newValue = ""; + if (valueListName in gHTMLAttr) { + var valueList = gHTMLAttr[valueListName]; + + let listLen = valueList.length; + useMenulist = listLen > 1; + if (listLen == 1) { + newValue = valueList[0]; + } + + // Note: For case where "value list" is actually just + // one (default) item, don't use menulist for that + if (useMenulist) { + gDialog.AddHTMLAttributeValueMenulist.removeAllItems(); + + // Rebuild the list + for (var i = 0; i < listLen; i++) { + if (valueList[i] == "-") { + // Signal for separator + var popup = gDialog.AddHTMLAttributeValueInput.menupopup; + if (popup) { + var sep = document.createXULElement("menuseparator"); + if (sep) { + popup.appendChild(sep); + } + } + } else { + gDialog.AddHTMLAttributeValueMenulist.appendItem( + valueList[i], + valueList[i] + ); + } + } + } + } + if (useMenulist) { + // Switch to using editable menulist instead of the input. + gDialog.AddHTMLAttributeValueMenulist.parentElement.collapsed = false; + gDialog.AddHTMLAttributeValueTextbox.parentElement.collapsed = true; + gDialog.AddHTMLAttributeValueInput = + gDialog.AddHTMLAttributeValueMenulist; + } else { + // No list: Use input instead of editable menulist. + gDialog.AddHTMLAttributeValueMenulist.parentElement.collapsed = true; + gDialog.AddHTMLAttributeValueTextbox.parentElement.collapsed = false; + gDialog.AddHTMLAttributeValueInput = gDialog.AddHTMLAttributeValueTextbox; + } + + // If attribute already exists in tree, use associated value, + // else use default found above + var existingValue = GetAndSelectExistingAttributeValue( + attName, + "HTMLAList" + ); + if (existingValue) { + newValue = existingValue; + } + + gDialog.AddHTMLAttributeValueInput.value = newValue; + + if (!existingValue) { + onInputHTMLAttributeValue(); + } + } +} + +function onInputHTMLAttributeValue() { + if (!gUpdateTreeValue) { + return; + } + + var name = TrimString(gDialog.AddHTMLAttributeNameInput.value); + if (!name) { + return; + } + + // Trim spaces only from left since we must allow spaces within the string + // (we always reset the input field's value below) + var value = TrimStringLeft(gDialog.AddHTMLAttributeValueInput.value); + if (value) { + // Do value filtering based on type of attribute + // (Do not use "forceInteger()" to avoid multiple + // resetting of input's value and flickering) + var selectedItem = gDialog.AddHTMLAttributeNameInput.selectedItem; + + if (selectedItem) { + if ( + selectedItem.getAttribute("forceOneChar") == "true" && + value.length > 1 + ) { + value = value.slice(0, 1); + } + + if (selectedItem.getAttribute("forceIntOrPercent") == "true") { + // Allow integer with optional "%" as last character + var percent = TrimStringRight(value).slice(-1); + value = value.replace(/\D+/g, ""); + if (percent == "%") { + value += percent; + } + } else if (selectedItem.getAttribute("forceInteger") == "true") { + value = value.replace(/\D+/g, ""); + } else if (selectedItem.getAttribute("forceSignedInteger") == "true") { + // Allow integer with optional "+" or "-" as first character + var sign = value[0]; + value = value.replace(/\D+/g, ""); + if (sign == "+" || sign == "-") { + value = sign + value; + } + } + + // Special case attributes + if (selectedItem.getAttribute("limitFirstChar") == "true") { + // Limit first character to letter, and all others to + // letters, numbers, and a few others + value = value + .replace(/^[^a-zA-Z\u0080-\uFFFF]/, "") + .replace(/[^a-zA-Z0-9_\.\-\:\u0080-\uFFFF]+/g, ""); + } + + // Update once only if it changed + if (value != gDialog.AddHTMLAttributeValueInput.value) { + gDialog.AddHTMLAttributeValueInput.value = value; + } + } + } + + // Update value in the tree list + // If not found, add new attribute + if (!UpdateExistingAttribute(name, value, "HTMLAList") && value) { + AddTreeItem(name, value, "HTMLAList", HTMLAttrs); + } +} + +function editHTMLAttributeValue(targetCell) { + if (IsNotTreeHeader(targetCell)) { + gDialog.AddHTMLAttributeValueInput.select(); + } +} + +// update the object with added and removed attributes +function UpdateHTMLAttributes() { + var HTMLAList = document.getElementById("HTMLAList"); + var i; + + // remove removed attributes + for (i = 0; i < HTMLRAttrs.length; i++) { + var name = HTMLRAttrs[i]; + + if (gElement.hasAttribute(name)) { + doRemoveAttribute(name); + } + } + + // Set added or changed attributes + for (i = 0; i < HTMLAList.children.length; i++) { + var item = HTMLAList.children[i]; + doSetAttribute(GetTreeItemAttributeStr(item), GetTreeItemValueStr(item)); + } +} + +function RemoveHTMLAttribute() { + // We only allow 1 selected item + if (gDialog.AddHTMLAttributeTree.view.selection.count) { + var item = getSelectedItem(gDialog.AddHTMLAttributeTree); + var attr = GetTreeItemAttributeStr(item); + + // remove the item from the attribute array + HTMLRAttrs[HTMLRAttrs.length] = attr; + RemoveNameFromAttArray(attr, HTMLAttrs); + + // Remove the item from the tree + item.remove(); + + // Clear inputs and selected item in tree + ClearHTMLInputWidgets(); + } +} + +function SelectHTMLTree(index) { + gDoOnSelectTree = false; + try { + gDialog.AddHTMLAttributeTree.selectedIndex = index; + } catch (e) {} + gDoOnSelectTree = true; +} |