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
@@ -54,10 +54,18 @@
                 this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
                 this.nMenu += 1;
             }
         }
     },
+
+    createMenus2 () {
+        let lNode = document.querySelectorAll("[contenteditable]");
+        for (let xNode of lNode) {
+            this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
+            this.nMenu += 1;
+        }
+    },
 
     rescanPage: function () {
         if (this.oTFPanel !== null) { this.oTFPanel.hide(); }
         if (this.oLxgPanel !== null) { this.oLxgPanel.hide(); }
         if (this.oGCPanel !== null) { this.oGCPanel.hide(); }
@@ -104,10 +112,20 @@
             showError(e);
         }
     }
 }
 
+
+/*
+    Node where a right click is done
+    Bug report: https://bugzilla.mozilla.org/show_bug.cgi?id=1325814
+*/
+let xRightClickedNode = null;
+document.addEventListener('contextmenu', function (xEvent) {
+    xRightClickedNode = xEvent.target;
+}, true);
+
 
 /*
     Connexion to the background
 */
 let xGrammalectePort = browser.runtime.connect({name: "content-script port"});
@@ -161,5 +179,6 @@
 
 /*
     Start
 */
 oGrammalecte.createMenus();
+oGrammalecte.createMenus2();

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
@@ -18,11 +18,11 @@
     border-radius: 50%;
     text-align: center;
     cursor: pointer;
     box-shadow: 0 0 0 0 hsla(210, 50%, 50%, .5);
     z-index: 2147483640; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */
-    animation: grammalecte-spin 2s ease 3;
+    animation: grammalecte-spin 2s ease 1;
 }
 .grammalecte_menu_main_button:hover {
     border: 4px solid hsla(210, 80%, 35%, .5);
     background-color: hsla(210, 80%, 55%, .5);
     animation: grammalecte-spin .5s linear infinite;

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
@@ -3,81 +3,83 @@
 "use strict";
 
 
 class GrammalecteMenu {
 
-    constructor (nMenu, xTextArea) {
+    constructor (nMenu, xNode) {
         this.sMenuId = "grammalecte_menu" + nMenu;
         this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
         this.xButton.onclick = () => { this.switchMenu(); };
-        this.xMenu = this._createMenu(xTextArea);
-        this._insertAfter(this.xButton, xTextArea);
-        this._insertAfter(this.xMenu, xTextArea);
+        this.xMenu = this._createMenu(xNode);
+        this._insertAfter(this.xButton, xNode);
+        this._insertAfter(this.xMenu, xNode);
     }
 
     _insertAfter (xNewNode, xReferenceNode) {
         xReferenceNode.parentNode.insertBefore(xNewNode, xReferenceNode.nextSibling);
     }
 
-    _createMenu (xTextArea) {
+    _createMenu (xNode) {
         try {
+            let sText = (xNode.tagName == "TEXTAREA") ? xNode.value : xNode.textContent;
             let xMenu = oGrammalecte.createNode("div", {id: this.sMenuId, className: "grammalecte_menu"});
+            xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"}));
             // Text formatter
-            let xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Formateur de texte"});
-            xTFButton.onclick = () => {
-            	this.switchMenu();
-                oGrammalecte.createTFPanel();
-                oGrammalecte.oTFPanel.start(xTextArea);
-                oGrammalecte.oTFPanel.show();
-            };
+            if (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.show();
+                };
+                xMenu.appendChild(xTFButton);
+            }
             // lexicographe
             let xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Lexicographe"});
             xLxgButton.onclick = () => {
-            	this.switchMenu();
+                this.switchMenu();
                 oGrammalecte.createLxgPanel();
                 oGrammalecte.oLxgPanel.clear();
                 oGrammalecte.oLxgPanel.show();
                 oGrammalecte.oLxgPanel.startWaitIcon();
                 xGrammalectePort.postMessage({
                     sCommand: "getListOfTokens",
-                    dParam: {sText: xTextArea.value},
-                    dInfo: {sTextAreaId: xTextArea.id}
+                    dParam: {sText: sText},
+                    dInfo: {sTextAreaId: xNode.id}
                 });
             };
+            xMenu.appendChild(xLxgButton);
             // Grammar checker
             let xGCButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item", textContent: "Correction grammaticale"});
             xGCButton.onclick = () => {
-            	this.switchMenu();
+                this.switchMenu();
                 oGrammalecte.createGCPanel();
-                oGrammalecte.oGCPanel.start(xTextArea);
+                oGrammalecte.oGCPanel.start(xNode);
                 oGrammalecte.oGCPanel.show();
                 oGrammalecte.oGCPanel.startWaitIcon();
                 xGrammalectePort.postMessage({
                     sCommand: "parseAndSpellcheck",
-                    dParam: {sText: xTextArea.value, sCountry: "FR", bDebug: false, bContext: false},
-                    dInfo: {sTextAreaId: xTextArea.id}
+                    dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false},
+                    dInfo: {sTextAreaId: xNode.id}
                 });
             };
+            xMenu.appendChild(xGCButton);
             // Conjugation tool
             let xConjButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_item_block", textContent: "Conjugueur"});
             let xConjButtonTab = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Onglet"});
             xConjButtonTab.onclick = () => {
-            	this.switchMenu();
-            	xGrammalectePort.postMessage({sCommand: "openConjugueurTab", dParam: null, dInfo: null});
+                this.switchMenu();
+                xGrammalectePort.postMessage({sCommand: "openConjugueurTab", dParam: null, dInfo: null});
             };
             let xConjButtonWin = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Fenêtre"});
             xConjButtonWin.onclick = () => {
-            	this.switchMenu();
-            	xGrammalectePort.postMessage({sCommand: "openConjugueurWindow", dParam: null, dInfo: null});
+                this.switchMenu();
+                xGrammalectePort.postMessage({sCommand: "openConjugueurWindow", dParam: null, dInfo: null});
             };
             xConjButton.appendChild(xConjButtonTab);
             xConjButton.appendChild(xConjButtonWin);
-            // Create
-            xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_header", textContent: "GRAMMALECTE"}));
-            xMenu.appendChild(xTFButton);
-            xMenu.appendChild(xLxgButton);
-            xMenu.appendChild(xGCButton);
             xMenu.appendChild(xConjButton);
             //xMenu.appendChild(oGrammalecte.createNode("img", {scr: browser.extension.getURL("img/logo-16.png")}));
             // can’t work, due to content-script policy: https://bugzilla.mozilla.org/show_bug.cgi?id=1267027
             xMenu.appendChild(oGrammalecte.createNode("div", {className: "grammalecte_menu_footer"}));
             return xMenu;
@@ -91,9 +93,9 @@
         this.xMenu.parentNode.removeChild(this.xMenu);
         this.xButton.parentNode.removeChild(this.xButton);
     }
 
     switchMenu () {
-    	let xMenu = document.getElementById(this.sMenuId);
+        let xMenu = document.getElementById(this.sMenuId);
         xMenu.style.display = (xMenu.style.display == "block") ? "none" : "block";
     }
 }

Index: gc_lang/fr/webext/content_scripts/panel_gc.js
==================================================================
--- gc_lang/fr/webext/content_scripts/panel_gc.js
+++ gc_lang/fr/webext/content_scripts/panel_gc.js
@@ -53,15 +53,15 @@
         this.oTooltip = new GrammalecteTooltip(this.xContentNode);
         this.xPanelContent.appendChild(this.xContentNode);
         this.oTAC = new GrammalecteTextAreaControl();
     }
 
-    start (xTextArea=null) {
+    start (xNode=null) {
         this.oTooltip.hide();
         this.clear();
-        if (xTextArea) {
-            this.oTAC.setTextArea(xTextArea);
+        if (xNode && xNode.tagName == "TEXTAREA") {
+            this.oTAC.setTextArea(xNode);
         }
     }
 
     clear () {
         while (this.xParagraphList.firstChild) {
@@ -448,11 +448,11 @@
             this._dParagraph.set(i, sText.slice(iStart, iEnd));
             i++;
             iStart = iEnd+1;
         }
         this._dParagraph.set(i, sText.slice(iStart));
-        console.log("Paragraphs number: " + (i+1));
+        //console.log("Paragraphs number: " + (i+1));
     }
 
     write () {
         if (this._xTextArea !== null) {
             let sText = "";

DELETED gc_lang/fr/webext/gce_sharedworker.js
Index: gc_lang/fr/webext/gce_sharedworker.js
==================================================================
--- gc_lang/fr/webext/gce_sharedworker.js
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
-    WORKER:
-    https://developer.mozilla.org/en-US/docs/Web/API/Worker
-    https://developer.mozilla.org/en-US/docs/Web/API/DedicatedWorkerGlobalScope
-
-
-    JavaScript sucks.
-    No module available in WebExtension at the moment! :(
-    No require, no import/export.
-
-    In Worker, we have importScripts() which imports everything in this scope.
-
-    In order to use the same base of code with XUL-addon for Thunderbird and SDK-addon for Firefox,
-    all modules have been “objectified”. And while they are still imported via “require”
-    in the previous extensions, they are loaded as background scripts in WebExtension sharing
-    the same memory space…
-
-    When JavaScript become a modern language, “deobjectify” the modules…
-
-    ATM, import/export are not available by default:
-    — Chrome 60 – behind the Experimental Web Platform flag in chrome:flags.
-    — Firefox 54 – behind the dom.moduleScripts.enabled setting in about:config.
-    — Edge 15 – behind the Experimental JavaScript Features setting in about:flags.
-
-    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
-    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
-*/
-
-"use strict";
-
-
-console.log("GC Engine SharedWorker [start]");
-//console.log(self);
-
-importScripts("grammalecte/helpers.js");
-importScripts("grammalecte/str_transform.js");
-importScripts("grammalecte/ibdawg.js");
-importScripts("grammalecte/text.js");
-importScripts("grammalecte/tokenizer.js");
-importScripts("grammalecte/fr/conj.js");
-importScripts("grammalecte/fr/mfsp.js");
-importScripts("grammalecte/fr/phonet.js");
-importScripts("grammalecte/fr/cregex.js");
-importScripts("grammalecte/fr/gc_options.js");
-importScripts("grammalecte/fr/gc_rules.js");
-importScripts("grammalecte/fr/gc_engine.js");
-importScripts("grammalecte/fr/lexicographe.js");
-importScripts("grammalecte/tests.js");
-/*
-    Warning.
-    Initialization can’t be completed at startup of the worker,
-    for we need the path of the extension to load data stored in JSON files.
-    This path is retrieved in background.js and passed with the event “init”.
-*/
-
-
-/*
-    Message Event Object
-    https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
-*/
-
-let xPort = null;
-
-function createResponse (sActionDone, result, dInfo, bError=false) {
-    return {
-        "sActionDone": sActionDone,
-        "result": result, // can be of any type
-        "dInfo": dInfo,
-        "bError": bError
-    };
-}
-
-function createErrorResult (e, sDescr="no description") {
-    return {
-        "sType": "error",
-        "sDescription": sDescr,
-        "sMessage": e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message
-    };
-}
-
-function showData (e) {
-    for (let sParam in e) {
-        console.log(sParam);
-        console.log(e[sParam]);
-    }
-}
-
-onconnect = function (e) {
-    console.log("[Sharedworker] START CONNECTION");
-    xPort = e.ports[0];
-
-    xPort.onmessage = function (e) {
-        console.log("[Sharedworker] ONMESSAGE");
-        let {sCommand, dParam, dInfo} = e.data;
-        console.log(e.data);
-        switch (sCommand) {
-            case "init":
-                init(dParam.sExtensionPath, dParam.sOptions, dParam.sContext, dInfo);
-                break;
-            case "parse":
-                parse(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
-                break;
-            case "parseAndSpellcheck":
-                parseAndSpellcheck(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
-                break;
-            case "getOptions":
-                getOptions(dInfo);
-                break;
-            case "getDefaultOptions":
-                getDefaultOptions(dInfo);
-                break;
-            case "setOptions":
-                setOptions(dParam.sOptions, dInfo);
-                break;
-            case "setOption":
-                setOption(dParam.sOptName, dParam.bValue, dInfo);
-                break;
-            case "resetOptions":
-                resetOptions(dInfo);
-                break;
-            case "textToTest":
-                textToTest(dParam.sText, dParam.sCountry, dParam.bDebug, dParam.bContext, dInfo);
-                break;
-            case "fullTests":
-                fullTests('{"nbsp":true, "esp":true, "unit":true, "num":true}', dInfo);
-                break;
-            case "getListOfTokens":
-                getListOfTokens(dParam.sText, dInfo);
-                break;
-            default:
-                console.log("Unknown command: " + sCommand);
-                showData(e.data);
-        }
-    }
-    //xPort.start();
-}
-
-let bInitDone = false;
-
-let oDict = null;
-let oTokenizer = null;
-let oLxg = null;
-let oTest = null;
-
-
-function init (sExtensionPath, sGCOptions="", sContext="JavaScript", dInfo={}) {
-    try {
-        if (!bInitDone) {
-            console.log("[Sharedworker] Loading… Extension path: " + sExtensionPath);
-            conj.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/conj_data.json"));
-            phonet.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/phonet_data.json"));
-            mfsp.init(helpers.loadFile(sExtensionPath + "/grammalecte/fr/mfsp_data.json"));
-            console.log("[Sharedworker] Modules have been initialized…");
-            gc_engine.load(sContext, sExtensionPath+"grammalecte/_dictionaries");
-            oDict = gc_engine.getDictionary();
-            oTest = new TestGrammarChecking(gc_engine, sExtensionPath+"/grammalecte/fr/tests_data.json");
-            oLxg = new Lexicographe(oDict);
-            if (sGCOptions !== "") {
-                gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
-            }
-            oTokenizer = new Tokenizer("fr");
-            //tests();
-            bInitDone = true;
-        } else {
-            console.log("[Sharedworker] Already initialized…")
-        }
-        // we always retrieve options from the gc_engine, for setOptions filters obsolete options
-        xPort.postMessage(createResponse("init", gc_engine.getOptions().gl_toString(), dInfo));
-    }
-    catch (e) {
-        helpers.logerror(e);
-        xPort.postMessage(createResponse("init", createErrorResult(e, "init failed"), dInfo, true));
-    }
-}
-
-function parse (sText, sCountry, bDebug, bContext, dInfo={}) {
-    let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext);
-    xPort.postMessage({sActionDone: "parse", result: aGrammErr, dInfo: dInfo});
-}
-
-function parseAndSpellcheck (sText, sCountry, bDebug, bContext, dInfo={}) {
-    let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext);
-    let aSpellErr = oTokenizer.getSpellingErrors(sText, oDict);
-    xPort.postMessage(createResponse("parseAndSpellcheck", {aGrammErr: aGrammErr, aSpellErr: aSpellErr}, dInfo));
-}
-
-function getOptions (dInfo={}) {
-    xPort.postMessage(createResponse("getOptions", gc_engine.getOptions().gl_toString(), dInfo));
-}
-
-function getDefaultOptions (dInfo={}) {
-    xPort.postMessage(createResponse("getDefaultOptions", gc_engine.getDefaultOptions().gl_toString(), dInfo));
-}
-
-function setOptions (sGCOptions, dInfo={}) {
-    gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
-    xPort.postMessage(createResponse("setOptions", gc_engine.getOptions().gl_toString(), dInfo));
-}
-
-function setOption (sOptName, bValue, dInfo={}) {
-    gc_engine.setOptions(new Map([ [sOptName, bValue] ]));
-    xPort.postMessage(createResponse("setOption", gc_engine.getOptions().gl_toString(), dInfo));
-}
-
-function resetOptions (dInfo={}) {
-    gc_engine.resetOptions();
-    xPort.postMessage(createResponse("resetOptions", gc_engine.getOptions().gl_toString(), dInfo));
-}
-
-function tests () {
-    console.log(conj.getConj("devenir", ":E", ":2s"));
-    console.log(mfsp.getMasForm("emmerdeuse", true));
-    console.log(mfsp.getMasForm("pointilleuse", false));
-    console.log(phonet.getSimil("est"));
-    let aRes = gc_engine.parse("Je suit...");
-    for (let oErr of aRes) {
-        console.log(text.getReadableError(oErr));
-    }
-}
-
-function textToTest (sText, sCountry, bDebug, bContext, dInfo={}) {
-    if (!gc_engine || !oDict) {
-        xPort.postMessage(createResponse("textToTest", "# Grammar checker or dictionary not loaded.", dInfo));
-        return;
-    }
-    let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext);
-    let sMsg = "";
-    for (let oErr of aGrammErr) {
-        sMsg += text.getReadableError(oErr) + "\n";
-    }
-    xPort.postMessage(createResponse("textToTest", sMsg, dInfo));
-}
-
-function fullTests (sGCOptions="", dInfo={}) {
-    if (!gc_engine || !oDict) {
-        xPort.postMessage(createResponse("fullTests", "# Grammar checker or dictionary not loaded.", dInfo));
-        return;
-    }
-    let dMemoOptions = gc_engine.getOptions();
-    if (sGCOptions) {
-        gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
-    }
-    let sMsg = "";
-    for (let sRes of oTest.testParse()) {
-        sMsg += sRes + "\n";
-        console.log(sRes);
-    }
-    gc_engine.setOptions(dMemoOptions);
-    xPort.postMessage(createResponse("fullTests", sMsg, dInfo));
-}
-
-
-// Lexicographer
-
-function getListOfTokens (sText, dInfo={}) {
-    try {
-        let aElem = [];
-        let aRes = null;
-        for (let oToken of oTokenizer.genTokens(sText)) {
-            aRes = oLxg.getInfoForToken(oToken);
-            if (aRes) {
-                aElem.push(aRes);
-            }
-        }
-        xPort.postMessage(createResponse("getListOfTokens", aElem, dInfo));
-    }
-    catch (e) {
-        helpers.logerror(e);
-        xPort.postMessage(createResponse("getListOfTokens", createErrorResult(e, "no tokens"), dInfo, true));
-    }
-}

Index: gc_lang/fr/webext/panel/main.html
==================================================================
--- gc_lang/fr/webext/panel/main.html
+++ gc_lang/fr/webext/panel/main.html
@@ -15,13 +15,13 @@
           <header id="logo">
             <img src="../img/logo-32.png">
           </header>
           <ul>
             <li class="select" data-page="home_page"><i class="select fa fa-star icon" data-page="home_page"></i></li>
-            <li class="select" data-page="help_page"><i class="select fa fa-question-circle icon" data-page="help_page"></i></li>
-            <li class="select" data-page="gc_options_page"><i class="select fa fa-cogs icon" data-page="gc_options_page"></i></li>
-            <li class="select" data-page="sc_options_page"><i class="select fa fa-cube icon" data-page="sc_options_page"></i></li>
+            <li class="select" data-page="help_page"><i class="select fa fa-cube icon" data-page="help_page"></i></li>
+            <li class="select" data-page="gc_options_page"><i class="select fa fa-cog icon" data-page="gc_options_page"></i></li>
+            <li class="select" data-page="sc_options_page"><i class="select fa fa-book icon" data-page="sc_options_page"></i></li>
             <li class="select" data-page="test_page"><i class="select fa fa-flask icon" data-page="test_page"></i></li>
           </ul>
         </nav>
       </header> <!-- #menu -->
 
@@ -49,11 +49,11 @@
             </p>
           </div>
         </section> <!-- #home_page -->
 
         <section id="help_page" class="page">
-          <h1>AIDE</h1>
+          <h1>INTERFACE</h1>
           <div id="help_section">
             <p>Grammalecte affiche un bouton d’accès au menu en bas à gauche des zones de texte usuelles pour accéder aux fonctionnalités existantes.</p>
             <p class="right"><img src="../img/menu_button1.png" title="bouton du menu" /></p>
             <p class="right"><img src="../img/menu_button2.png" title="menu" /></p>
             <p>Pour les autres zones de texte (HTML éditable), il faut sélectionner le texte et utiliser le menu contextuel.</p>