diff --git a/chrome/content/zotero/elements/itemBox.js b/chrome/content/zotero/elements/itemBox.js
index 6526cb3224..3c95695763 100644
--- a/chrome/content/zotero/elements/itemBox.js
+++ b/chrome/content/zotero/elements/itemBox.js
@@ -2198,6 +2198,12 @@
this._focusNextField(1);
}
+ focusField(fieldName) {
+ let field = this.shadowRoot.querySelector(`[fieldname="${fieldName}"][ztabindex]`);
+ if (!field) return false;
+ return this._focusNextField(field.getAttribute('ztabindex'));
+ }
+
/**
* Advance the field focus forward or backward
*
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
index ed114ecee2..56142093be 100644
--- a/chrome/content/zotero/zoteroPane.js
+++ b/chrome/content/zotero/zoteroPane.js
@@ -1801,6 +1801,55 @@ var ZoteroPane = new function()
});
+ this.duplicateAndConvertSelectedItem = async function () {
+ if (this.getSelectedItems().length != 1
+ || !['book', 'bookSection'].includes(this.getSelectedItems()[0].itemType)) {
+ throw new Error('duplicateAndConvertSelectedItem requires a single book or bookSection to be selected');
+ }
+
+ let authorCreatorType = Zotero.CreatorTypes.getID('author');
+ let bookAuthorCreatorType = Zotero.CreatorTypes.getID('bookAuthor');
+
+ let original = this.getSelectedItems()[0];
+ let duplicate = await this.duplicateSelectedItem();
+ if (!duplicate) return null;
+
+ if (duplicate.itemType == 'book') {
+ duplicate.setType(Zotero.ItemTypes.getID('bookSection'));
+ for (let i = 0; i < duplicate.numCreators(); i++) {
+ let creator = duplicate.getCreator(i);
+ if (creator.creatorTypeID == authorCreatorType) {
+ creator.creatorTypeID = bookAuthorCreatorType;
+ }
+ duplicate.setCreator(i, creator);
+ }
+ }
+ else {
+ duplicate.setField('title', false); // So bookTitle becomes title
+ duplicate.setType(Zotero.ItemTypes.getID('book'));
+ // Get creators from the original item because setType() will have changed the types
+ let creators = original.getCreators()
+ // Remove authors of the individual book section
+ .filter(creator => creator.creatorTypeID !== authorCreatorType);
+ for (let creator of creators) {
+ if (creator.creatorTypeID == bookAuthorCreatorType) {
+ creator.creatorTypeID = authorCreatorType;
+ }
+ }
+ duplicate.setCreators(creators);
+ }
+
+ duplicate.addRelatedItem(original);
+ original.addRelatedItem(duplicate);
+
+ await original.saveTx({ skipDateModifiedUpdate: true });
+ await duplicate.saveTx();
+
+ document.getElementById('zotero-editpane-item-box').focusField('title');
+ return duplicate;
+ };
+
+
/**
* Return whether every selected item can be deleted from the current
* collection context (library, trash, collection, etc.).
@@ -3084,6 +3133,7 @@ var ZoteroPane = new function()
'toggleRead',
'addToCollection',
'removeItems',
+ 'duplicateAndConvert',
'duplicateItem',
'restoreToLibrary',
'moveToTrash',
@@ -3363,6 +3413,12 @@ var ZoteroPane = new function()
}
}
else if (!collectionTreeRow.isPublications()) {
+ if (item.itemType == 'book' || item.itemType == 'bookSection') {
+ menu.childNodes[m.duplicateAndConvert].setAttribute('label', Zotero.getString('pane.items.menu.duplicateAndConvert.'
+ + (item.itemType == 'book' ? 'toBookSection' : 'toBook')));
+ show.add(m.duplicateAndConvert);
+ }
+
show.add(m.duplicateItem);
}
}
diff --git a/chrome/content/zotero/zoteroPane.xhtml b/chrome/content/zotero/zoteroPane.xhtml
index 3c548d798b..ea5dac541c 100644
--- a/chrome/content/zotero/zoteroPane.xhtml
+++ b/chrome/content/zotero/zoteroPane.xhtml
@@ -971,6 +971,7 @@
+
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
index 3cd74abddb..fd7993eb52 100644
--- a/chrome/locale/en-US/zotero/zotero.properties
+++ b/chrome/locale/en-US/zotero/zotero.properties
@@ -359,6 +359,8 @@ pane.items.menu.createParent = Create Parent Item…
pane.items.menu.createParent.multiple = Create Parent Items
pane.items.menu.renameAttachments = Rename File from Parent Metadata
pane.items.menu.renameAttachments.multiple = Rename Files from Parent Metadata
+pane.items.menu.duplicateAndConvert.toBookSection = Create Book Section
+pane.items.menu.duplicateAndConvert.toBook = Create Book from Book Section
pane.items.showItemInLibrary = Show Item in Library
pane.items.letter.oneParticipant = Letter to %S