From 568b88e342bcc76d13717825be5f7d821e522109 Mon Sep 17 00:00:00 2001 From: Abe Jellinek Date: Tue, 11 Oct 2022 01:28:27 -0400 Subject: [PATCH] Add "Capitalize" text transform to creator context menu (#2801) --- chrome/content/zotero/elements/itemBox.js | 71 ++++++++++++++++++----- chrome/content/zotero/xpcom/utilities | 2 +- chrome/locale/en-US/zotero/zotero.dtd | 1 + 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/chrome/content/zotero/elements/itemBox.js b/chrome/content/zotero/elements/itemBox.js index fa4cf31bca..d5e92b6cdc 100644 --- a/chrome/content/zotero/elements/itemBox.js +++ b/chrome/content/zotero/elements/itemBox.js @@ -72,6 +72,7 @@ + @@ -190,10 +191,15 @@ } }); + this._id('zotero-field-transform-menu').addEventListener('popupshowing', () => { + this._id('creator-transform-title-case').disabled = !this.canTextTransformField(document.popupNode, 'title'); + this._id('creator-transform-sentence-case').disabled = !this.canTextTransformField(document.popupNode, 'sentence'); + }); + this._id('creator-transform-title-case').addEventListener('command', - () => this.textTransform(document.popupNode, 'title')); + () => this.textTransformField(document.popupNode, 'title')); this._id('creator-transform-sentence-case').addEventListener('command', - () => this.textTransform(document.popupNode, 'sentence')); + () => this.textTransformField(document.popupNode, 'sentence')); this._id('zotero-creator-transform-menu').addEventListener('popupshowing', (event) => { var row = document.popupNode.closest('tr'); @@ -212,6 +218,9 @@ this._id('creator-transform-swap-names').addEventListener('command', event => this.swapNames(event)); + + this._id('creator-transform-capitalize').addEventListener('command', + event => this.capitalizeCreatorName(event)); this._notifierID = Zotero.Notifier.registerObserver(this, ['item'], 'itemBox'); } @@ -918,9 +927,11 @@ firstlast.lastChild.hidden = true; } - if (this.editable && fieldMode == 0) { + if (this.editable) { firstlast.oncontextmenu = (event) => { document.popupNode = firstlast; + this._id('creator-transform-swap-names').hidden = fieldMode > 0; + this._id('creator-transform-capitalize').disabled = !this.canCapitalizeCreatorName(td.parentNode); this._id('zotero-creator-transform-menu').openPopupAtScreen( event.screenX + 1, event.screenY + 1, @@ -2057,26 +2068,34 @@ } } - /** - * TODO: work with textboxes too - */ - async textTransform(label, mode) { - var val = this._getFieldValue(label); + textTransformString(val, mode) { switch (mode) { case 'title': - var newVal = Zotero.Utilities.capitalizeTitle(val.toLowerCase(), true); - break; + return Zotero.Utilities.capitalizeTitle(val.toLowerCase(), true); case 'sentence': // capitalize the first letter, including after beginning punctuation // capitalize after ?, ! and remove space(s) before those as well as colon analogous to capitalizeTitle function // also deal with initial punctuation here - open quotes and Spanish beginning punctuation marks - newVal = val.toLowerCase().replace(/\s*:/, ":"); - newVal = newVal.replace(/(([\?!]\s*|^)([\'\"¡¿“‘„«\s]+)?[^\s])/g, function (x) { + val = val.toLowerCase().replace(/\s*:/, ":"); + val = val.replace(/(([\?!]\s*|^)([\'\"¡¿“‘„«\s]+)?[^\s])/g, function (x) { return x.replace(/\s+/m, " ").toUpperCase();}); - break; + return val; default: - throw new Error("Invalid transform mode '" + mode + "' in ItemBox.textTransform()"); + throw new Error("Invalid transform mode '" + mode + "' in ItemBox.textTransformString()"); } + } + + canTextTransformField(label, mode) { + let val = this._getFieldValue(label); + return this.textTransformString(val, mode) != val; + } + + /** + * TODO: work with textboxes too + */ + async textTransformField(label, mode) { + var val = this._getFieldValue(label); + var newVal = this.textTransformString(val, mode); this._setFieldValue(label, newVal); var fieldName = label.getAttribute('fieldname'); this._modifyField(fieldName, newVal); @@ -2163,6 +2182,30 @@ } } + canCapitalizeCreatorName(row) { + var fields = this.getCreatorFields(row); + return fields.firstName && Zotero.Utilities.capitalizeName(fields.firstName) != fields.firstName + || fields.lastName && Zotero.Utilities.capitalizeName(fields.lastName) != fields.lastName; + } + + /** + * @return {Promise} + */ + async capitalizeCreatorName(event) { + var row = document.popupNode.closest('tr'); + var typeBox = row.querySelector('.creator-type-label'); + var creatorIndex = parseInt(typeBox.getAttribute('fieldname').split('-')[1]); + var fields = this.getCreatorFields(row); + fields.firstName = fields.firstName && Zotero.Utilities.capitalizeName(fields.firstName); + fields.lastName = fields.lastName && Zotero.Utilities.capitalizeName(fields.lastName); + this.modifyCreator(creatorIndex, fields); + if (this.saveOnEdit) { + // See note in transformText() + await this.blurOpenField(); + await this.item.saveTx(); + } + } + /** * @return {Promise} */ diff --git a/chrome/content/zotero/xpcom/utilities b/chrome/content/zotero/xpcom/utilities index 4d8d7d3e92..3143d5518d 160000 --- a/chrome/content/zotero/xpcom/utilities +++ b/chrome/content/zotero/xpcom/utilities @@ -1 +1 @@ -Subproject commit 4d8d7d3e92cbc3b4d62b82478e212a6f63b9a35f +Subproject commit 3143d5518d0044152bdca2b11e5ba2de92b5101f diff --git a/chrome/locale/en-US/zotero/zotero.dtd b/chrome/locale/en-US/zotero/zotero.dtd index 35bb63b9c1..6f86130d63 100644 --- a/chrome/locale/en-US/zotero/zotero.dtd +++ b/chrome/locale/en-US/zotero/zotero.dtd @@ -114,6 +114,7 @@ +