Refactor itemBox.js create element
This commit is contained in:
parent
b3aa0fe5ec
commit
e4ad1862d1
1 changed files with 178 additions and 164 deletions
|
@ -609,15 +609,15 @@
|
|||
rowLabel.className = "meta-label";
|
||||
rowLabel.setAttribute('fieldname', fieldName);
|
||||
|
||||
let valueElement = this.createValueElement(
|
||||
let valueElement = this.createFieldValueElement(
|
||||
val, fieldName
|
||||
);
|
||||
|
||||
if (fieldName) {
|
||||
let label = document.createElement('label');
|
||||
label.className = 'key';
|
||||
label.textContent = Zotero.ItemFields.getLocalizedString(fieldName);
|
||||
label.setAttribute("id", `itembox-field-${fieldName}-label`);
|
||||
let label = this.createLabelElement({
|
||||
text: Zotero.ItemFields.getLocalizedString(fieldName),
|
||||
id: `itembox-field-${fieldName}-label`,
|
||||
});
|
||||
rowLabel.appendChild(label);
|
||||
valueElement.setAttribute('aria-labelledby', label.id);
|
||||
}
|
||||
|
@ -853,35 +853,6 @@
|
|||
});
|
||||
this._showCreatorTypeGuidance = false;
|
||||
}
|
||||
|
||||
// On click of the label, toggle the focus of the value field
|
||||
for (let label of this.querySelectorAll(".meta-label > label")) {
|
||||
if (!this.editable) {
|
||||
break;
|
||||
}
|
||||
|
||||
label.addEventListener('mousedown', (event) => {
|
||||
// Prevent default focus/blur behavior - we implement our own below
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
label.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
let labelWrapper = label.closest(".meta-label");
|
||||
if (labelWrapper.nextSibling.contains(document.activeElement)) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
else {
|
||||
let valueField = labelWrapper.nextSibling.firstChild;
|
||||
if (valueField.id === "item-type-menu") {
|
||||
valueField.querySelector("menupopup").openPopup();
|
||||
return;
|
||||
}
|
||||
labelWrapper.nextSibling.firstChild.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._ensureButtonsFocusable();
|
||||
this._updateCreatorButtonsStatus();
|
||||
|
@ -925,89 +896,30 @@
|
|||
let labelElem = document.createElement("div");
|
||||
labelElem.classList.add("meta-label");
|
||||
|
||||
let label = document.createElement("label");
|
||||
let labelID = `itembox-custom-row-${row.rowID}-label`;
|
||||
label.id = labelID;
|
||||
label.classList.add("key");
|
||||
let label = this.createLabelElement({
|
||||
id: labelID,
|
||||
text: row.label.text,
|
||||
});
|
||||
label.dataset.l10nId = row.label.l10nID;
|
||||
|
||||
label.addEventListener('mousedown', (event) => {
|
||||
// Prevent default focus/blur behavior - we implement our own below
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
label.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
let labelWrapper = label.closest(".meta-label");
|
||||
if (labelWrapper.nextSibling.contains(document.activeElement)) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
else {
|
||||
labelWrapper.nextSibling.firstChild.focus();
|
||||
}
|
||||
});
|
||||
|
||||
labelElem.appendChild(label);
|
||||
|
||||
let dataElem = document.createElement("div");
|
||||
dataElem.classList.add("meta-data");
|
||||
|
||||
let valueElem = document.createXULElement("editable-text");
|
||||
valueElem.id = `itembox-custom-row-${row.rowID}-value`;
|
||||
valueElem.classList.add("value", "custom-row-value");
|
||||
|
||||
if (row.multiline) {
|
||||
valueElem.setAttribute('multiline', true);
|
||||
}
|
||||
else if (row.nowrap) {
|
||||
// Usual fields occupy all available space and keep info on one line
|
||||
valueElem.setAttribute("nowrap", true);
|
||||
}
|
||||
|
||||
if (typeof row.editable == "boolean") {
|
||||
let editable = row.editable;
|
||||
if (!this.editable) editable = false;
|
||||
valueElem.toggleAttribute("readonly", !editable);
|
||||
}
|
||||
|
||||
valueElem.addEventListener("focus", () => {
|
||||
if (row.multiline) {
|
||||
valueElem.setAttribute("min-lines", 6);
|
||||
let editable = row.editable ?? true;
|
||||
if (!this.editable) editable = false;
|
||||
let valueElem = this.createValueElement({
|
||||
id: `itembox-custom-row-${row.rowID}-value`,
|
||||
classList: ["custom-row-value"],
|
||||
isMultiline: row.multiline,
|
||||
isLong: !row.nowrap,
|
||||
editable,
|
||||
attributes: {
|
||||
"aria-labelledby": labelID
|
||||
}
|
||||
});
|
||||
valueElem.addEventListener("blur", () => {
|
||||
if (row.multiline) {
|
||||
valueElem.setAttribute("min-lines", 1);
|
||||
}
|
||||
let onSetData = Zotero.ItemPaneManager.getInfoRowHook(row.rowID, "onSetData");
|
||||
if (onSetData) {
|
||||
try {
|
||||
onSetData({
|
||||
rowID: row.rowID,
|
||||
item: this.item,
|
||||
tabType: this.tabType,
|
||||
editable: this.editable,
|
||||
value: valueElem.value
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
valueElem.setAttribute('tight', true);
|
||||
|
||||
// Regardless, align the text in the label consistently, following the locale's direction
|
||||
if (Zotero.rtl) {
|
||||
valueElem.style.textAlign = 'right';
|
||||
}
|
||||
else {
|
||||
valueElem.style.textAlign = 'left';
|
||||
}
|
||||
|
||||
valueElem.setAttribute("aria-labelledby", labelID);
|
||||
|
||||
dataElem.appendChild(valueElem);
|
||||
|
||||
|
@ -1142,10 +1054,10 @@
|
|||
var labelWrapper = document.createElement('div');
|
||||
labelWrapper.className = "meta-label";
|
||||
labelWrapper.setAttribute("fieldname", "itemType");
|
||||
var label = document.createElement("label");
|
||||
label.className = "key";
|
||||
label.id = "itembox-field-itemType-label";
|
||||
label.innerText = Zotero.getString("zotero.items.itemType");
|
||||
var label = this.createLabelElement({
|
||||
id: "itembox-field-itemType-label",
|
||||
text: Zotero.getString("zotero.items.itemType")
|
||||
});
|
||||
labelWrapper.appendChild(label);
|
||||
var rowData = document.createElement('div');
|
||||
rowData.className = "meta-data";
|
||||
|
@ -1270,10 +1182,10 @@
|
|||
}
|
||||
|
||||
rowLabel.appendChild(labelWrapper);
|
||||
var label = document.createElement("label");
|
||||
label.setAttribute('id', 'creator-type-label-inner');
|
||||
label.className = 'key';
|
||||
label.textContent = Zotero.getString('creatorTypes.' + Zotero.CreatorTypes.getName(typeID));
|
||||
let label = this.createLabelElement({
|
||||
id: 'creator-type-label-inner',
|
||||
text: Zotero.getString('creatorTypes.' + Zotero.CreatorTypes.getName(typeID))
|
||||
});
|
||||
labelWrapper.appendChild(label);
|
||||
|
||||
var rowData = document.createElement("div");
|
||||
|
@ -1285,7 +1197,7 @@
|
|||
|
||||
var fieldName = 'creator-' + rowIndex + '-lastName';
|
||||
var lastNameElem = firstlast.appendChild(
|
||||
this.createValueElement(
|
||||
this.createFieldValueElement(
|
||||
lastName,
|
||||
fieldName,
|
||||
)
|
||||
|
@ -1294,7 +1206,7 @@
|
|||
lastNameElem.placeholder = this._defaultLastName;
|
||||
fieldName = 'creator-' + rowIndex + '-firstName';
|
||||
var firstNameElem = firstlast.appendChild(
|
||||
this.createValueElement(
|
||||
this.createFieldValueElement(
|
||||
firstName,
|
||||
fieldName,
|
||||
)
|
||||
|
@ -1471,16 +1383,16 @@
|
|||
var rowLabel = document.createElement("div");
|
||||
rowLabel.className = "meta-label";
|
||||
rowLabel.setAttribute("fieldname", field);
|
||||
var label = document.createElement('label');
|
||||
label.className = 'key';
|
||||
label.textContent = Zotero.ItemFields.getLocalizedString(field);
|
||||
label.setAttribute("id", `itembox-field-${field}-label`);
|
||||
let label = this.createLabelElement({
|
||||
text: Zotero.ItemFields.getLocalizedString(field),
|
||||
id: `itembox-field-${field}-label`
|
||||
});
|
||||
rowLabel.appendChild(label);
|
||||
|
||||
var rowData = document.createElement('div');
|
||||
rowData.className = "meta-data date-box";
|
||||
|
||||
var elem = this.createValueElement(
|
||||
var elem = this.createFieldValueElement(
|
||||
Zotero.Date.multipartToStr(value),
|
||||
field
|
||||
);
|
||||
|
@ -1687,18 +1599,46 @@
|
|||
return openLink;
|
||||
}
|
||||
|
||||
createValueElement(valueText, fieldName) {
|
||||
valueText += '';
|
||||
|
||||
if (fieldName) {
|
||||
var fieldID = Zotero.ItemFields.getID(fieldName);
|
||||
createLabelElement({ text, id, attributes, classList }) {
|
||||
let label = document.createElement('label');
|
||||
label.classList.add('key', ...classList || []);
|
||||
if (text) label.textContent = text;
|
||||
if (id) label.id = id;
|
||||
if (attributes) {
|
||||
for (let [key, value] of Object.entries(attributes)) {
|
||||
label.setAttribute(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
let isMultiline = Zotero.ItemFields.isMultiline(fieldName);
|
||||
let isLong = Zotero.ItemFields.isLong(fieldName);
|
||||
|
||||
var valueElement = document.createXULElement("editable-text");
|
||||
valueElement.className = 'value';
|
||||
// On click of the label, toggle the focus of the value field
|
||||
if (this.editable) {
|
||||
label.addEventListener('mousedown', (event) => {
|
||||
// Prevent default focus/blur behavior - we implement our own below
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
label.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
let labelWrapper = label.closest(".meta-label");
|
||||
if (labelWrapper.nextSibling.contains(document.activeElement)) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
else {
|
||||
let valueField = labelWrapper.nextSibling.firstChild;
|
||||
if (valueField.id === "item-type-menu") {
|
||||
valueField.querySelector("menupopup").openPopup();
|
||||
return;
|
||||
}
|
||||
labelWrapper.nextSibling.firstChild.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
createValueElement({ isMultiline, isLong, editable, text, tooltipText, id, attributes, classList } = {}) {
|
||||
let valueElement = document.createXULElement("editable-text");
|
||||
valueElement.classList.add('value', ...classList || []);
|
||||
if (isMultiline) {
|
||||
valueElement.setAttribute('multiline', true);
|
||||
}
|
||||
|
@ -1706,9 +1646,7 @@
|
|||
// Usual fields occupy all available space and keep info on one line
|
||||
valueElement.setAttribute("nowrap", true);
|
||||
}
|
||||
|
||||
|
||||
if (this._fieldIsClickable(fieldName)) {
|
||||
if (editable) {
|
||||
valueElement.addEventListener("focus", e => this.showEditor(e.target));
|
||||
valueElement.addEventListener("blur", e => this.hideEditor(e.target));
|
||||
}
|
||||
|
@ -1716,13 +1654,51 @@
|
|||
valueElement.setAttribute('readonly', true);
|
||||
}
|
||||
|
||||
valueElement.setAttribute('id', `itembox-field-value-${fieldName}`);
|
||||
valueElement.setAttribute('fieldname', fieldName);
|
||||
if (id) valueElement.id = id;
|
||||
if (tooltipText) valueElement.tooltipText = tooltipText;
|
||||
if (attributes) {
|
||||
for (let [key, value] of Object.entries(attributes)) {
|
||||
valueElement.setAttribute(key, value);
|
||||
}
|
||||
}
|
||||
valueElement.setAttribute('tight', true);
|
||||
|
||||
valueElement.value = text;
|
||||
if (text) {
|
||||
valueElement.dir = 'auto';
|
||||
}
|
||||
// If not, assume it follows the locale's direction
|
||||
else {
|
||||
valueElement.dir = Zotero.dir;
|
||||
}
|
||||
|
||||
// Regardless, align the text in the label consistently, following the locale's direction
|
||||
if (Zotero.rtl) {
|
||||
valueElement.style.textAlign = 'right';
|
||||
}
|
||||
else {
|
||||
valueElement.style.textAlign = 'left';
|
||||
}
|
||||
return valueElement;
|
||||
}
|
||||
|
||||
createFieldValueElement(valueText, fieldName) {
|
||||
valueText += '';
|
||||
|
||||
if (fieldName) {
|
||||
var fieldID = Zotero.ItemFields.getID(fieldName);
|
||||
}
|
||||
|
||||
let isMultiline = Zotero.ItemFields.isMultiline(fieldName);
|
||||
let isLong = Zotero.ItemFields.isLong(fieldName);
|
||||
|
||||
let attributes = {
|
||||
fieldname: fieldName,
|
||||
};
|
||||
|
||||
switch (fieldName) {
|
||||
case 'itemType':
|
||||
valueElement.setAttribute('itemTypeID', valueText);
|
||||
attributes.itemTypeID = valueText;
|
||||
valueText = Zotero.ItemTypes.getLocalizedString(valueText);
|
||||
break;
|
||||
|
||||
|
@ -1741,33 +1717,25 @@
|
|||
break;
|
||||
}
|
||||
|
||||
let tooltipText;
|
||||
if (fieldID) {
|
||||
// Display the SQL date as a tooltip for date fields
|
||||
// TEMP - filingDate
|
||||
if (Zotero.ItemFields.isFieldOfBase(fieldID, 'date') || fieldName == 'filingDate') {
|
||||
valueElement.tooltipText = Zotero.Date.multipartToSQL(this.item.getField(fieldName, true));
|
||||
tooltipText = Zotero.Date.multipartToSQL(this.item.getField(fieldName, true));
|
||||
}
|
||||
}
|
||||
|
||||
valueElement.value = valueText;
|
||||
let valueElement = this.createValueElement({
|
||||
isMultiline,
|
||||
isLong,
|
||||
editable: this._fieldIsClickable(fieldName),
|
||||
text: valueText,
|
||||
tooltipText,
|
||||
id: `itembox-field-value-${fieldName}`,
|
||||
attributes
|
||||
});
|
||||
|
||||
// Attempt to make bidi things work automatically:
|
||||
// If we have text to work off of, let the layout engine try to guess the text direction
|
||||
if (valueText) {
|
||||
valueElement.dir = 'auto';
|
||||
}
|
||||
// If not, assume it follows the locale's direction
|
||||
else {
|
||||
valueElement.dir = Zotero.dir;
|
||||
}
|
||||
|
||||
// Regardless, align the text in the label consistently, following the locale's direction
|
||||
if (Zotero.rtl) {
|
||||
valueElement.style.textAlign = 'right';
|
||||
}
|
||||
else {
|
||||
valueElement.style.textAlign = 'left';
|
||||
}
|
||||
if (!fieldName.startsWith('creator-')) {
|
||||
// autocomplete for creator names is added in addCreatorRow
|
||||
this.addAutocompleteToElement(valueElement);
|
||||
|
@ -1836,13 +1804,25 @@
|
|||
}
|
||||
|
||||
async showEditor(elem) {
|
||||
Zotero.debug(`Showing editor for ${elem.getAttribute('fieldname')}`);
|
||||
let isCustomRow = elem.classList.contains("custom-row-value");
|
||||
|
||||
var fieldName = elem.getAttribute('fieldname');
|
||||
let isMultiline = Zotero.ItemFields.isMultiline(fieldName);
|
||||
if (isCustomRow) {
|
||||
isMultiline = elem.hasAttribute("multiline");
|
||||
}
|
||||
|
||||
// Multiline field will be at least 6 lines
|
||||
if (Zotero.ItemFields.isMultiline(fieldName)) {
|
||||
if (isMultiline) {
|
||||
elem.setAttribute("min-lines", 6);
|
||||
}
|
||||
|
||||
if (isCustomRow) {
|
||||
return;
|
||||
}
|
||||
|
||||
Zotero.debug(`Showing editor for ${fieldName}`);
|
||||
|
||||
var [field, creatorIndex, creatorField] = fieldName.split('-');
|
||||
let value;
|
||||
if (field == 'creator') {
|
||||
|
@ -2099,20 +2079,54 @@
|
|||
if (this.ignoreBlur || !textbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
var fieldName = textbox.getAttribute('fieldname');
|
||||
|
||||
let isMultiline = Zotero.ItemFields.isMultiline(fieldName);
|
||||
let isCustomRow = textbox.classList.contains("custom-row-value");
|
||||
|
||||
if (isCustomRow) {
|
||||
isMultiline = textbox.hasAttribute("multiline");
|
||||
}
|
||||
|
||||
if (isMultiline) {
|
||||
textbox.setAttribute("min-lines", 1);
|
||||
}
|
||||
|
||||
if (isCustomRow) {
|
||||
let rowID = textbox.closest(".meta-row").dataset.customRowId;
|
||||
let onSetData = Zotero.ItemPaneManager.getInfoRowHook(rowID, "onSetData");
|
||||
if (onSetData) {
|
||||
try {
|
||||
onSetData({
|
||||
rowID,
|
||||
item: this.item,
|
||||
tabType: this.tabType,
|
||||
editable: this.editable,
|
||||
value: textbox.value
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.logError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle cases where creator autocomplete doesn't trigger
|
||||
// the textentered and change events handled in showEditor
|
||||
if (textbox.getAttribute('fieldname').startsWith('creator-')) {
|
||||
if (fieldName.startsWith('creator-')) {
|
||||
this.handleCreatorAutoCompleteSelect(textbox);
|
||||
}
|
||||
|
||||
Zotero.debug(`Hiding editor for ${textbox.getAttribute('fieldname')}`);
|
||||
|
||||
Zotero.debug(`Hiding editor for ${fieldName}`);
|
||||
|
||||
// Prevent autocomplete breakage in Firefox 3
|
||||
if (textbox.mController) {
|
||||
textbox.mController.input = null;
|
||||
}
|
||||
|
||||
var fieldName = textbox.getAttribute('fieldname');
|
||||
|
||||
// Multiline fields go back to occupying as much space as needed
|
||||
if (Zotero.ItemFields.isMultiline(fieldName)) {
|
||||
|
|
Loading…
Reference in a new issue