Index: doc/build.md ================================================================== --- doc/build.md +++ doc/build.md @@ -5,11 +5,12 @@ * Python 3.6 * Firefox Nightly * NodeJS * npm - * jpm + * jpm : https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm + * web-ext : https://developer.mozilla.org/fr/Add-ons/WebExtensions/Getting_started_with_web-ext * Thunderbird ## Commands ## Index: gc_lang/fr/build.py ================================================================== --- gc_lang/fr/build.py +++ gc_lang/fr/build.py @@ -7,11 +7,11 @@ import helpers def build (sLang, dVars, spLangPack): "complementary build launched from make.py" - createFirefoxExtension(sLang, dVars) + #createFirefoxExtension(sLang, dVars) createWebExtension(sLang, dVars) createThunderbirdExtension(sLang, dVars, spLangPack) def createWebExtension (sLang, dVars): 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 @@ -49,10 +49,12 @@ oGCPanel: null, oMessageBox: null, xRightClickedNode: null, + + xObserver: null, listenRightClick: function () { // Node where a right click is done // Bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=1325814 document.addEventListener('contextmenu', function (xEvent) { @@ -89,10 +91,35 @@ this.nMenu += 1; } } } }, + + observePage: function () { + /* + When a textarea is added via jascript we add the menu :) + */ + this.xObserver = new MutationObserver(function (mutations) { + mutations.forEach(function (mutation) { + for (let i = 0; i < mutation.addedNodes.length; i++){ + if (mutation.addedNodes[i].tagName == "TEXTAREA") { + oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, mutation.addedNodes[i])); + oGrammalecte.nMenu += 1; + } else if (mutation.addedNodes[i].getElementsByTagName) { + for (let xNode of mutation.addedNodes[i].getElementsByTagName("textarea")) { + oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode)); + oGrammalecte.nMenu += 1; + } + } + } + }); + }); + this.xObserver.observe(document.body, { + childList: true, + subtree: true + }); + }, rescanPage: function () { if (this.oTFPanel !== null) { this.oTFPanel.hide(); } if (this.oLxgPanel !== null) { this.oLxgPanel.hide(); } if (this.oGCPanel !== null) { this.oGCPanel.hide(); } @@ -296,5 +323,6 @@ /* Start */ oGrammalecte.listenRightClick(); oGrammalecte.createMenus(); +oGrammalecte.observePage(); Index: gc_lang/fr/webext/content_scripts/menu.css ================================================================== --- gc_lang/fr/webext/content_scripts/menu.css +++ gc_lang/fr/webext/content_scripts/menu.css @@ -6,14 +6,15 @@ /* Button */ .grammalecte_menu_main_button { position: absolute; + box-sizing: border-box; display: none; margin: -8px 0 0 -8px; - width: 8px; - height: 8px; + width: 16px; + height: 16px; background-color: hsla(210, 80%, 80%, .5); border: 4px solid hsla(210, 80%, 60%, .5); border-top: 4px solid hsla(210, 100%, 40%, .7); border-bottom: 4px solid hsla(210, 100%, 40%, .7); border-radius: 50%; @@ -61,10 +62,18 @@ border: 3px solid hsl(210, 50%, 30%); box-shadow: 0px 0px 2px hsla(210, 10%, 10%, .5); background-color: hsl(210, 50%, 30%); font-family: "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif; z-index: 2147483640; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */ + text-align: left; +} + +.grammalecte_menu > div { + line-height: 21px; +} +.grammalecte_menu > div.grammalecte_menu_close_button { + line-height: 18px; } .grammalecte_menu_close_button { float: right; margin: 2px 2px 0 0; Index: gc_lang/fr/webext/content_scripts/menu.js ================================================================== --- gc_lang/fr/webext/content_scripts/menu.js +++ gc_lang/fr/webext/content_scripts/menu.js @@ -4,74 +4,90 @@ class GrammalecteMenu { constructor (nMenu, xNode) { + this.xNode = xNode; this.sMenuId = "grammalecte_menu" + nMenu; this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "}); this.xButton.onclick = () => { this.switchMenu(); }; this.xButton.style.zIndex = (xNode.style.zIndex.search(/^[0-9]+$/) !== -1) ? (parseInt(xNode.style.zIndex) + 1).toString() : xNode.style.zIndex; - this.xMenu = this._createMenu(xNode); - this._insertAfter(this.xButton, xNode); - this._insertAfter(this.xMenu, xNode); - this._createListenersOnReferenceNode(xNode); + this.xMenu = this._createMenu(); + + let xStyle = window.getComputedStyle(this.xNode); + let nMarginTop = -1 * (8 + parseInt(xStyle.marginBottom.replace('px', ''), 10)); + + let xNodeInsertAfter = this.xNode; + if (document.location.host == "twitter.com" && this.xNode.classList.contains('rich-editor')) { + xNodeInsertAfter = this.xNode.parentNode; + } + + this._insertAfter(this.xButton, xNodeInsertAfter, nMarginTop); + this._insertAfter(this.xMenu, xNodeInsertAfter, nMarginTop + 8); + this._createListeners(); } - _insertAfter (xNewNode, xReferenceNode) { + _insertAfter (xNewNode, xReferenceNode, nMarginTop) { xReferenceNode.parentNode.insertBefore(xNewNode, xReferenceNode.nextSibling); + xNewNode.style.marginTop = nMarginTop + "px"; } - _createListenersOnReferenceNode (xNode) { - xNode.addEventListener('focus', (e) => { + _createListeners () { + this.xNode.addEventListener('focus', (e) => { this.xButton.style.display = "block"; }); - xNode.addEventListener('blur', (e) => { + /*this.xNode.addEventListener('blur', (e) => { window.setTimeout(() => {this.xButton.style.display = "none";}, 300); - }); + });*/ + } + + _getText () { + return (this.xNode.tagName == "TEXTAREA") ? this.xNode.value.normalize("NFC") : this.xNode.innerText.normalize("NFC"); } - _createMenu (xNode) { + _createMenu () { try { let xMenu = oGrammalecte.createNode("div", {id: this.sMenuId, className: "grammalecte_menu"}); let xCloseButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_close_button", textContent: "×"} ); - xCloseButton.onclick = () => { this.switchMenu(); } + xCloseButton.onclick = () => { + this.xButton.style.display = "none"; + this.switchMenu(); + } xMenu.appendChild(xCloseButton); xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"})); // Text formatter - if (xNode.tagName == "TEXTAREA") { + if (this.xNode.tagName == "TEXTAREA") { let xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"}); xTFButton.onclick = () => { this.switchMenu(); oGrammalecte.createTFPanel(); - oGrammalecte.oTFPanel.start(xNode); + oGrammalecte.oTFPanel.start(this.xNode); oGrammalecte.oTFPanel.show(); }; xMenu.appendChild(xTFButton); } // lexicographe let xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"}); xLxgButton.onclick = () => { this.switchMenu(); - let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.innerText; oGrammalecte.startLxgPanel(); xGrammalectePort.postMessage({ sCommand: "getListOfTokens", - dParam: {sText: sText}, - dInfo: {sTextAreaId: xNode.id} + dParam: {sText: this._getText()}, + dInfo: {sTextAreaId: this.xNode.id} }); }; xMenu.appendChild(xLxgButton); // Grammar checker let xGCButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"}); xGCButton.onclick = () => { this.switchMenu(); - let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.innerText; - oGrammalecte.startGCPanel(xNode); + oGrammalecte.startGCPanel(this.xNode); xGrammalectePort.postMessage({ sCommand: "parseAndSpellcheck", - dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false}, - dInfo: {sTextAreaId: xNode.id} + dParam: {sText: this._getText(), sCountry: "FR", bDebug: false, bContext: false}, + dInfo: {sTextAreaId: this.xNode.id} }); }; xMenu.appendChild(xGCButton); // Conjugation tool let xConjButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"}); Index: make.py ================================================================== --- make.py +++ make.py @@ -286,11 +286,11 @@ xParser.add_argument("-d", "--dict", help="generate FSA dictionary", action="store_true") xParser.add_argument("-t", "--tests", help="run unit tests", action="store_true") xParser.add_argument("-p", "--perf", help="run performance tests", action="store_true") xParser.add_argument("-pm", "--perf_memo", help="run performance tests and store results in perf_memo.txt", action="store_true") xParser.add_argument("-js", "--javascript", help="JavaScript build for Firefox", action="store_true") - xParser.add_argument("-fx", "--firefox", help="Launch Firefox Developper for Adden-SDK testing", action="store_true") + xParser.add_argument("-fx", "--firefox", help="Launch Firefox Nightly for WebExtension testing", action="store_true") xParser.add_argument("-we", "--web_ext", help="Launch Firefox Nightly for WebExtension testing", action="store_true") xParser.add_argument("-tb", "--thunderbird", help="Launch Thunderbird", action="store_true") xParser.add_argument("-i", "--install", help="install the extension in Writer (path of unopkg must be set in config.ini)", action="store_true") xArgs = xParser.parse_args() @@ -347,16 +347,17 @@ if xArgs.perf or xArgs.perf_memo: hDst = open("./gc_lang/"+sLang+"/perf_memo.txt", "a", encoding="utf-8", newline="\n") if xArgs.perf_memo else None tests.perf(sVersion, hDst) # Firefox - if xArgs.firefox: + if False: + # obsolete with helpers.cd("_build/xpi/"+sLang): spfFirefox = dVars['win_fx_dev_path'] if platform.system() == "Windows" else dVars['linux_fx_dev_path'] os.system('jpm run -b "' + spfFirefox + '"') - if xArgs.web_ext: + if xArgs.web_ext or xArgs.firefox: with helpers.cd("_build/webext/"+sLang): spfFirefox = dVars['win_fx_nightly_path'] if platform.system() == "Windows" else dVars['linux_fx_nightly_path'] os.system(r'web-ext run --firefox="' + spfFirefox + '" --browser-console --firefox-profile=debug') # Thunderbird