Index: gc_lang/fr/webext/background.js ================================================================== --- gc_lang/fr/webext/background.js +++ gc_lang/fr/webext/background.js @@ -331,11 +331,12 @@ /* Context Menu */ // Analyze browser.contextMenus.create({ id: "grammar_checker_editable", title: "Analyser cette zone de texte", contexts: ["editable"] }); -browser.contextMenus.create({ id: "grammar_checker_selection", title: "Analyser la sélection", contexts: ["selection"] }); +browser.contextMenus.create({ id: "grammar_checker_selection", title: "Analyser la sélection", contexts: ["selection"] }); +browser.contextMenus.create({ id: "grammar_checker_iframe", title: "Analyser le contenu de ce cadre", contexts: ["frame"] }); browser.contextMenus.create({ id: "grammar_checker_page", title: "Analyser la page", contexts: ["all"] }); browser.contextMenus.create({ id: "separator_tools", type: "separator", contexts: ["all"] }); // Tools browser.contextMenus.create({ id: "conjugueur_tab", title: "Conjugueur [onglet]", contexts: ["all"] }); browser.contextMenus.create({ id: "conjugueur_window", title: "Conjugueur [fenêtre]", contexts: ["all"] }); @@ -354,10 +355,13 @@ // analyze case "grammar_checker_editable": case "grammar_checker_page": sendCommandToTab(xTab.id, xInfo.menuItemId); break; + case "grammar_checker_iframe": + sendCommandToTab(xTab.id, xInfo.menuItemId, xInfo.frameId); + break; case "grammar_checker_selection": sendCommandToTab(xTab.id, xInfo.menuItemId, xInfo.selectionText); oWorkerHandler.xGCEWorker.postMessage({ sCommand: "parseAndSpellcheck", dParam: {sText: xInfo.selectionText, sCountry: "FR", bDebug: false, bContext: false}, ADDED gc_lang/fr/webext/content_scripts/api.js Index: gc_lang/fr/webext/content_scripts/api.js ================================================================== --- gc_lang/fr/webext/content_scripts/api.js +++ gc_lang/fr/webext/content_scripts/api.js @@ -0,0 +1,56 @@ +// JavaScript + +"use strict"; + + +const oGrammalecteAPI = { + // functions callable from within pages + + sVersion: "1.0", + + parse: function (arg1) { + let xNode = null; + if (typeof(arg1) === 'string') { + if (document.getElementById(arg1)) { + xNode = document.getElementById(arg1); + } else { + this.parseText(arg1); + } + } + else if (arg1 instanceof HTMLElement) { + xNode = arg1; + } + if (xNode) { + console.log("xnode"); + if (xNode.tagName == "INPUT" || xNode.tagName == "TEXTAREA" || xNode.isContentEditable) { + this.parseNode(xNode); + } + else if (xNode.tagName == "IFRAME") { + this.parseText(xNode.contentWindow.document.body.innerText); + } + else { + this.parseText(xNode.innerText); + } + } + }, + + parseNode: function (xNode) { + console.log("parseNode"); + if (xNode instanceof HTMLElement) { + let xEvent = new CustomEvent("GrammalecteCall", { detail: {sCommand: "parseNode", xNode: xNode} }); + document.dispatchEvent(xEvent); + } else { + console.log("[Grammalecte API] Error: parameter is not a HTML node."); + } + }, + + parseText: function (sText) { + console.log("parseText"); + if (typeof(sText) === "string") { + let xEvent = new CustomEvent("GrammalecteCall", { detail: {sCommand: "parseText", sText: sText} }); + document.dispatchEvent(xEvent); + } else { + console.log("[Grammalecte API] Error: parameter is not a text."); + } + } +} Index: gc_lang/fr/webext/content_scripts/init.js ================================================================== --- gc_lang/fr/webext/content_scripts/init.js +++ gc_lang/fr/webext/content_scripts/init.js @@ -13,10 +13,11 @@ "use strict"; function showError (e) { + // console can’t display error objects from content scripts console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message); } // Chrome don’t follow the W3C specification: // https://browserext.github.io/browserext/ @@ -86,34 +87,20 @@ _prepareButtons: function (oOptions) { if (oOptions.hasOwnProperty("ui_options")) { this.oOptions = oOptions.ui_options; // textarea for (let xNode of document.getElementsByTagName("textarea")) { - if (xNode.dataset.grammalecte_callbutton && document.getElementById(xNode.dataset.grammalecte_callbutton)) { - let xButton = document.getElementById(xNode.dataset.grammalecte_callbutton) - xButton.onclick = () => { - oGrammalecte.startGCPanel(xNode); - }; - this.lButton.push(xButton); - this.nButton += 1; - } - else if (this.oOptions.textarea && xNode.style.display !== "none" && xNode.style.visibility !== "hidden" && xNode.getAttribute("spellcheck") !== "false") { + if (this.oOptions.textarea && xNode.style.display !== "none" && xNode.style.visibility !== "hidden" && xNode.getAttribute("spellcheck") !== "false" + && !(xNode.dataset.grammalecte_button && xNode.dataset.grammalecte_button == "false")) { this.lButton.push(new GrammalecteButton(this.nButton, xNode)); this.nButton += 1; } } // editable nodes for (let xNode of document.querySelectorAll("[contenteditable]")) { - if (xNode.dataset.grammalecte_callbutton && document.getElementById(xNode.dataset.grammalecte_callbutton)) { - let xButton = document.getElementById(xNode.dataset.grammalecte_callbutton) - xButton.onclick = () => { - oGrammalecte.startGCPanel(xNode); - }; - this.lButton.push(xButton); - this.nButton += 1; - } - else if (this.oOptions.editablenode && xNode.style.display !== "none" && xNode.style.visibility !== "hidden") { + if (this.oOptions.editablenode && xNode.style.display !== "none" && xNode.style.visibility !== "hidden" + && !(xNode.dataset.grammalecte_button && xNode.dataset.grammalecte_button == "false")) { this.lButton.push(new GrammalecteButton(this.nButton, xNode)); this.nButton += 1; } } } @@ -385,19 +372,63 @@ oGrammalecte.startGCPanel(oGrammalecte.getPageText()); break; case "grammar_checker_selection": oGrammalecte.startGCPanel(result, false); // result is the selected text // selected text is sent to the GC worker in the background script. + break; + case "grammar_checker_iframe": + console.log("[Grammalecte] selected iframe: ", result); + if (document.activeElement.tagName == "IFRAME") { + //console.log(document.activeElement.id); frameId given by result is different than frame.id + oGrammalecte.startGCPanel(document.activeElement.contentWindow.document.body.innerText); + } else { + oGrammalecte.showMessage("Erreur. Le cadre sur lequel vous avez cliqué n’a pas pu être identifié. Sélectionnez le texte à corriger et relancez le correcteur via le menu contextuel."); + } break; // rescan page command case "rescanPage": oGrammalecte.rescanPage(); break; default: console.log("[Content script] Unknown command: " + sActionDone); } }); + + + +/* + Callable API for the webpage. + The API script must be injected this way to be callable by the page +*/ +let xScriptGrammalecteAPI = document.createElement("script"); +xScriptGrammalecteAPI.src = browser.extension.getURL("content_scripts/api.js"); +document.documentElement.appendChild(xScriptGrammalecteAPI); + +document.addEventListener("GrammalecteCall", function (xEvent) { + // GrammalecteCall events are dispatched by functions in the API + try { + let oCommand = xEvent.detail; + switch (oCommand.sCommand) { + case "parseNode": + if (oCommand.xNode) { + oGrammalecte.startGCPanel(oCommand.xNode); + } + break; + case "parseText": + if (oCommand.sText) { + oGrammalecte.startGCPanel(oCommand.sText); + } + break; + default: + console.log("[Grammalecte] Event: Unknown command", oCommand.sCommand); + } + } + catch (e) { + showError(e); + } +}); + /* Other messages from background */ Index: gc_lang/fr/webext/manifest.json ================================================================== --- gc_lang/fr/webext/manifest.json +++ gc_lang/fr/webext/manifest.json @@ -93,10 +93,11 @@ "description": "Ouvre l’éditeur lexical" } }, "web_accessible_resources": [ + "content_scripts/api.js", "content_scripts/panel.css", "content_scripts/panel_tf.css", "content_scripts/panel_gc.css", "content_scripts/panel_lxg.css", "content_scripts/panel_conj.css",