diff --git a/chrome/content/zotero/elements/itemBox.js b/chrome/content/zotero/elements/itemBox.js index b87f7c392e..8702f159ab 100644 --- a/chrome/content/zotero/elements/itemBox.js +++ b/chrome/content/zotero/elements/itemBox.js @@ -1114,15 +1114,19 @@ insertCustomRow(rowElem, position = "end") { switch (position) { case "start": { - this._infoTable.prepend(rowElem); + let itemTypeRow = this._infoTable.querySelector(".meta-label[fieldname=itemType]")?.parentElement; + if (itemTypeRow) { + this._infoTable.insertBefore(rowElem, itemTypeRow); + } + else { + this._infoTable.append(rowElem); + } break; } case "afterCreators": { // The `_firstRowBeforeCreators` is actually the first row after creator rows if (this._firstRowBeforeCreators) { this._infoTable.insertBefore(rowElem, this._firstRowBeforeCreators); - // Update the anchor node for creator rows - this._firstRowBeforeCreators = rowElem; } else { this._infoTable.append(rowElem); diff --git a/chrome/content/zotero/xpcom/pluginAPI/itemPaneManager.js b/chrome/content/zotero/xpcom/pluginAPI/itemPaneManager.js index f8890fc799..df26e6169e 100644 --- a/chrome/content/zotero/xpcom/pluginAPI/itemPaneManager.js +++ b/chrome/content/zotero/xpcom/pluginAPI/itemPaneManager.js @@ -437,6 +437,21 @@ } this._refresh([rowID]); } + + get data() { + let options = this.options; + // Since `rowID` is mapped to a namespaced key including `pluginID`, + // sorting by it produces a stable visual order grouped by plugin, + if (Array.isArray(options) && options.length > 1) { + options = options.sort((a, b) => + String(a.rowID ?? "").localeCompare(String(b.rowID ?? "")) + ); + } + return { + updateID: this.updateID, + options, + }; + } }