Index: gc_lang/fr/webext/background.js ================================================================== --- gc_lang/fr/webext/background.js +++ gc_lang/fr/webext/background.js @@ -195,10 +195,16 @@ type: "separator", contexts: ["selection"] }); // Editable content +browser.contextMenus.create({ + id: "rightClickTFEditableNode", + title: "Formateur de texte (zone de texte)", + contexts: ["editable"] +}); + browser.contextMenus.create({ id: "rightClickLxgEditableNode", title: "Lexicographe (zone de texte)", contexts: ["editable"] }); @@ -266,14 +272,15 @@ // xTab = https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/Tab // confusing: no way to get the node where we click?! switch (xInfo.menuItemId) { // editable node // page - case "rightClickGCEditableNode": + case "rightClickTFEditableNode": case "rightClickLxgEditableNode": - case "rightClickGCPage": + case "rightClickGCEditableNode": case "rightClickLxgPage": + case "rightClickGCPage": sendCommandToTab(xInfo.menuItemId, xTab.id); break; // selected text case "rightClickGCSelectedText": sendCommandToTab("rightClickGCSelectedText", xTab.id); 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 @@ -35,19 +35,22 @@ Array.filter(document.getElementsByClassName(sContainerClass), function (oElem) { oElem.appendChild(img); }); } */ + const oGrammalecte = { nMenu: 0, lMenu: [], oTFPanel: null, oLxgPanel: null, oGCPanel: null, + + oMessageBox: null, xRightClickedNode: null, listenRightClick: function () { // Node where a right click is done @@ -112,10 +115,17 @@ if (this.oGCPanel === null) { this.oGCPanel = new GrammalecteGrammarChecker("grammalecte_gc_panel", "Grammalecte", 500, 700); this.oGCPanel.insertIntoPage(); } }, + + createMessageBox: function () { + if (this.oMessageBox === null) { + this.oMessageBox = new GrammalecteMessageBox("grammalecte_message_box", "Grammalecte", 400, 300); + this.oMessageBox.insertIntoPage(); + } + }, startGCPanel: function (xNode=null) { oGrammalecte.createGCPanel(); oGrammalecte.oGCPanel.clear(); oGrammalecte.oGCPanel.show(); @@ -127,10 +137,22 @@ oGrammalecte.createLxgPanel(); oGrammalecte.oLxgPanel.clear(); oGrammalecte.oLxgPanel.show(); oGrammalecte.oLxgPanel.startWaitIcon(); }, + + startFTPanel: function (xNode=null) { + oGrammalecte.createTFPanel(); + oGrammalecte.oTFPanel.start(xNode); + oGrammalecte.oTFPanel.show(); + }, + + showMessage: function (sMessage) { + oGrammalecte.createMessageBox(); + oGrammalecte.oMessageBox.setMessage(sMessage); + oGrammalecte.oMessageBox.show(); + }, getPageText: function () { let sPageText = document.body.innerText; let nPos = sPageText.indexOf("__grammalecte_panel__"); if (nPos >= 0) { @@ -197,13 +219,11 @@ sCommand: "parseAndSpellcheck", dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false}, dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id} }); } else { - oGrammalecte.startGCPanel(); - oGrammalecte.oGCPanel.addMessage("Erreur. Node introuvable… Sélectionnez le texte à corriger et relancez le correcteur via le menu contextuel."); - oGrammalecte.oGCPanel.stopWaitIcon(); + oGrammalecte.showMessage("Erreur. Le node 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; case "rightClickGCPage": oGrammalecte.startGCPanel(); xGrammalectePort.postMessage({ @@ -225,13 +245,11 @@ sCommand: "getListOfTokens", dParam: {sText: sText}, dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id} }); } else { - oGrammalecte.startLxgPanel(); - oGrammalecte.oLxgPanel.addMessage("Erreur. Node introuvable… Sélectionnez le texte à analyser et relancez le lexicographe via le menu contextuel."); - oGrammalecte.oLxgPanel.stopWaitIcon(); + oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié. Sélectionnez le texte à analyser et relancez le lexicographe via le menu contextuel."); } break; case "rightClickLxgPage": oGrammalecte.startLxgPanel(); xGrammalectePort.postMessage({ @@ -241,10 +259,22 @@ }); break; case "rightClickLxgSelectedText": oGrammalecte.startLxgPanel(); // selected text is sent to the GC worker in the background script. + break; + // Text formatter command + case "rightClickTFEditableNode": + if (oGrammalecte.xRightClickedNode !== null) { + if (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") { + oGrammalecte.startFTPanel(oGrammalecte.xRightClickedNode); + } else { + oGrammalecte.showMessage("Cette zone de texte n’est pas réellement un champ de formulaire, mais un node HTML éditable. Le formateur de texte n’est pas disponible pour ce type de champ de saisie."); + } + } else { + oGrammalecte.showMessage("Erreur. Le node sur lequel vous avez cliqué n’a pas pu être identifié."); + } break; // rescan page command case "rescanPage": oGrammalecte.rescanPage(); break; ADDED gc_lang/fr/webext/content_scripts/message_box.css Index: gc_lang/fr/webext/content_scripts/message_box.css ================================================================== --- gc_lang/fr/webext/content_scripts/message_box.css +++ gc_lang/fr/webext/content_scripts/message_box.css @@ -0,0 +1,65 @@ +/* + CSS + Message box for Grammalecte +*/ + +.grammalecte_message_box { + padding: 0; + margin: 0; + position: fixed; + box-sizing: content-box; + z-index: 2147483641; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */ + border: 2px solid hsl(210, 10%, 50%); + border-radius: 10px 10px 10px 10px; + background-color: hsl(210, 0%, 100%); + color: hsl(0, 0%, 0%); + font-family: "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif; + box-shadow: 0 0 2px 1px hsla(210, 50%, 50%, .5); + line-height: normal; + text-shadow: none; + text-decoration: none; +} +.grammalecte_message_box img { + display: inline-block; + margin: 0; + padding: 0; +} + +.grammalecte_message_box_bar { + position: sticky; + width: 100%; + background-color: hsl(210, 0%, 90%); + border-radius: 10px 10px 0 0; + border-bottom: 1px solid hsl(210, 10%, 80%); + color: hsl(210, 10%, 4%); + font-size: 20px; +} +.grammalecte_message_box_title { + padding: 10px 20px; +} +.grammalecte_message_box_label { + display: inline-block; + padding: 0 10px; +} +.grammalecte_message_box_invisible_marker { + position: absolute; + /*visibility: hidden;*/ + font-size: 6px; + color: hsl(210, 0%, 90%); /* same color than panel_bar background */ +} + +.grammalecte_message_box_content { + position: absolute; + min-width: 100%; + height: calc(100% - 55px); /* panel height - title_bar */ + overflow: auto; +} + +.grammalecte_message_box_message { + margin: 10px; + padding: 10px; + border-radius: 5px; + background-color: hsl(0, 50%, 40%); + color: hsl(0, 50%, 96%); + font-size: 20px; +} ADDED gc_lang/fr/webext/content_scripts/message_box.js Index: gc_lang/fr/webext/content_scripts/message_box.js ================================================================== --- gc_lang/fr/webext/content_scripts/message_box.js +++ gc_lang/fr/webext/content_scripts/message_box.js @@ -0,0 +1,74 @@ +// JavaScript +// Panel creator + +"use strict"; + + +class GrammalecteMessageBox { + + constructor (sId, sTitle, nWidth, nHeight) { + this.sId = sId; + this.nWidth = nWidth; + this.nHeight = nHeight; + this.xMessageBoxBar = oGrammalecte.createNode("div", {className: "grammalecte_message_box_bar"}); + this.xMessageBoxContent = oGrammalecte.createNode("div", {className: "grammalecte_message_box_content"}); + this.xMessageBox = this._createPanel(sTitle); + this.center(); + } + + _createPanel (sTitle) { + try { + let xMessageBox = oGrammalecte.createNode("div", {id: this.sId, className: "grammalecte_message_box"}); + this.xMessageBoxBar.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_message_box_invisible_marker", textContent: "__grammalecte_panel__"})); + this.xMessageBoxBar.appendChild(this._createButtons()); + let xTitle = oGrammalecte.createNode("div", {className: "grammalecte_panel_title"}); + xTitle.appendChild(this._createLogo()); + xTitle.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_message_box_label", textContent: sTitle})); + this.xMessageBoxBar.appendChild(xTitle); + xMessageBox.appendChild(this.xMessageBoxBar); + xMessageBox.appendChild(this.xMessageBoxContent); + return xMessageBox; + } + catch (e) { + showError(e); + } + } + + _createLogo () { + let xImg = document.createElement("img"); + xImg.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAC8UlEQVQ4jX3TbUgTcRwH8P89ddu5u9tt082aZmpFEU4tFz0QGTUwCi0heniR9MSUIKRaD0RvIlKigsooo+iNFa0XJYuwIjEK19OcDtPElsG0ktyp591t7u7+vUh7MPX3+vf5/n8/+P0BmKJIPUUVlh2rdVVeesWlzEybqg+bFOsoylnqPmNavGFfknV2Omu2Lvja3vxAURKJib3opHizu8riLK6gjRyuKgmoSoMRFENRUqfXTzvBGK62LC2uoFkOl4RhjQ8+qWt7dPNE3sbdp+2LXbsGe9qb4rIo/BfwFy6nWQ4ThWGNDzbcfu29dMDh2nHU7CypYNLmzTda0/L5cNuzmDQi/A4Y27k6eQxLI79wS/11D0AAMNvs6XT6ojVJjJEgTbMy2BT77xBMp09KcpaWV1uc41jQoi0NdUHfjeOO9WWn7AVF7s7n986SithPJGeupBh2PCSP/xxqxAp3eq6wuUV7Wc6MSZIEhA8vHjbfOe/OcW3zmAuKy+nUzAyD2bow8ODaEROFq8AyZ5WBYdEZXGqGxZ61HJV+9HYCJRbTNA0QBA40HWunaKN5dKg/DBKxeCIe09Th/m4MJwiMSZmLEzMQAABQRuNqgu8NYX3doTcMpvCkLbtQZ2AJkrPOZG1zlnY13T+Hy9EehY90h57eqcorcZ/lctZuMzAsOjLEqwNv66/6vZcPYRBC+C3cGaBxhSet2av1BpYgTTY7k5y2JPT41slIR6Axv8R9nnOs+4Pf+2r992uOxGVJwgAAAEINfgt3BGgsESWtWas1iGDyl+CT/u7WpvxNFRc4x7qtBoZFhSFejb7z1fq9NYfjsiT+cwcQavBruCOgU4SIGo18amuoq3Js3FNlynVtH385+s53ze+t8cRkURx3yMTTRBAEQVAUXbFlf3XystJKA2NExeFBdWASDAAA+MQACCEEmqbJ0b6PMC7JwhDU8YFHV5u9NZ64LErT/oW/63tPV6uJwmKoOND78u7Fg5NhAAD4CVbzY9cwrWQrAAAAAElFTkSuQmCC"; + return xImg; + } + + _createButtons () { + let xButtonLine = oGrammalecte.createNode("div", {className: "grammalecte_panel_commands"}); + xButtonLine.appendChild(this._createCloseButton()); + return xButtonLine; + } + + _createCloseButton () { + let xButton = oGrammalecte.createNode("div", {className: "grammalecte_close_button", textContent: "×", title: "Fermer la fenêtre"}); + xButton.onclick = function () { this.hide(); }.bind(this); // better than writing “let that = this;” before the function? + return xButton; + } + + insertIntoPage () { + document.body.appendChild(this.xMessageBox); + } + + show () { + this.xMessageBox.style.display = "block"; + } + + hide () { + this.xMessageBox.style.display = "none"; + } + + setMessage (sMessage) { + this.xMessageBoxContent.textContent = sMessage; + } + + center () { + this.xMessageBox.style = `top: 50%; left: 50%; width: ${this.nWidth}px; height: ${this.nHeight}px; margin-top: -${this.nHeight/2}px; margin-left: -${this.nWidth/2}px;`; + } +} Index: gc_lang/fr/webext/content_scripts/panel_tf.js ================================================================== --- gc_lang/fr/webext/content_scripts/panel_tf.js +++ gc_lang/fr/webext/content_scripts/panel_tf.js @@ -160,17 +160,19 @@ } /* Actions */ - start (xTextArea) { - this.xTextArea = xTextArea; - if (bChrome) { - browser.storage.local.get("tf_options", this.setOptions.bind(this)); - } else { - let xPromise = browser.storage.local.get("tf_options"); - xPromise.then(this.setOptions.bind(this), this.reset.bind(this)); + start (xNode) { + if (xNode !== null && xNode.tagName == "TEXTAREA") { + this.xTextArea = xNode; + if (bChrome) { + browser.storage.local.get("tf_options", this.setOptions.bind(this)); + } else { + let xPromise = browser.storage.local.get("tf_options"); + xPromise.then(this.setOptions.bind(this), this.reset.bind(this)); + } } } switchGroup (sOptName) { if (document.getElementById(sOptName).dataset.selected == "true") { Index: gc_lang/fr/webext/manifest.json ================================================================== --- gc_lang/fr/webext/manifest.json +++ gc_lang/fr/webext/manifest.json @@ -51,18 +51,20 @@ "css": [ "content_scripts/panel.css", "content_scripts/panel_tf.css", "content_scripts/panel_gc.css", "content_scripts/panel_lxg.css", + "content_scripts/message_box.css", "content_scripts/menu.css" ], "js": [ "content_scripts/panel.js", "grammalecte/fr/textformatter.js", "content_scripts/panel_tf.js", "content_scripts/panel_gc.js", "content_scripts/panel_lxg.js", + "content_scripts/message_box.js", "content_scripts/menu.js", "content_scripts/init.js" ], "run_at": "document_end" },