diff --git a/chrome/content/zotero/elements/noteEditor.js b/chrome/content/zotero/elements/noteEditor.js index f23497a27c..27176ea185 100644 --- a/chrome/content/zotero/elements/noteEditor.js +++ b/chrome/content/zotero/elements/noteEditor.js @@ -60,6 +60,8 @@ window.addEventListener("unload", this.destroy); var shadow = this.attachShadow({ mode: "open" }); + MozXULElement.insertFTLIfNeeded('mozilla/textActions.ftl'); + document.l10n.connectRoot(shadow); // var s1 = document.createElement("link"); // s1.rel = "stylesheet"; diff --git a/chrome/content/zotero/note.xhtml b/chrome/content/zotero/note.xhtml index 430bc719d0..999c1ae68c 100644 --- a/chrome/content/zotero/note.xhtml +++ b/chrome/content/zotero/note.xhtml @@ -23,6 +23,7 @@ Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this); Services.scriptloader.loadSubScript("resource://zotero/require.js", this); + Services.scriptloader.loadSubScript("chrome://global/content/customElements.js", this); Services.scriptloader.loadSubScript("chrome://zotero/content/elements/shadowAutocompleteInput.js", this); Services.scriptloader.loadSubScript("chrome://zotero/content/elements/noteEditor.js", this); Services.scriptloader.loadSubScript("chrome://zotero/content/elements/relatedBox.js", this); diff --git a/chrome/content/zotero/xpcom/editorInstance.js b/chrome/content/zotero/xpcom/editorInstance.js index 497ae2c6d4..b2d0b527e9 100644 --- a/chrome/content/zotero/xpcom/editorInstance.js +++ b/chrome/content/zotero/xpcom/editorInstance.js @@ -78,6 +78,7 @@ class EditorInstance { Zotero.Prefs.registerObserver('note.css', this._handleStyleChange), Zotero.Prefs.registerObserver('layout.spellcheckDefault', this._handleSpellCheckChange, true) ]; + this._spellChecker = null; // Run Cut/Copy/Paste with chrome privileges this._iframeWindow.wrappedJSObject.zoteroExecCommand = function (doc, command, ui, value) { @@ -872,8 +873,31 @@ class EditorInstance { } let firstElementChild = this._popup.firstElementChild; + let showSeparator = false; let suggestionCount = spellChecker.addSuggestionsToMenuOnParent(this._popup, firstElementChild, 5); if (suggestionCount) { + showSeparator = true; + } + if (spellChecker.overMisspelling) { + let addToDictionary = this._popup.ownerDocument.createXULElement('menuitem'); + addToDictionary.setAttribute('data-l10n-id', 'text-action-spell-add-to-dictionary'); + addToDictionary.addEventListener('command', () => { + spellChecker.addToDictionary(); + }); + this._popup.insertBefore(addToDictionary, firstElementChild); + showSeparator = true; + } + if (spellChecker.canUndo()) { + let undo = this._popup.ownerDocument.createXULElement('menuitem'); + undo.setAttribute('data-l10n-id', 'text-action-spell-undo-add-to-dictionary'); + undo.addEventListener('command', () => { + spellChecker.undoAddToDictionary(); + }); + this._popup.insertBefore(undo, firstElementChild); + showSeparator = true; + } + + if (showSeparator) { let separator = this._popup.ownerDocument.createXULElement('menuseparator'); this._popup.insertBefore(separator, firstElementChild); } @@ -883,10 +907,13 @@ class EditorInstance { } _getSpellChecker() { - let editingSession = this._iframeWindow.docShell.editingSession; - return new InlineSpellChecker( - editingSession.getEditorForWindow(this._iframeWindow) - ); + if (!this._spellChecker) { + let editingSession = this._iframeWindow.docShell.editingSession; + this._spellChecker = new InlineSpellChecker( + editingSession.getEditorForWindow(this._iframeWindow) + ); + } + return this._spellChecker; } async _ensureNoteCreated() {