Grammalecte  Changes On Branch 686c43591b259880

Changes In Branch comunicate Through [686c43591b] Excluding Merge-Ins

This is equivalent to a diff from 9b6a855c65 to 686c43591b

2020-03-10
08:41
[fx] cancel code cosmetics check-in: 4cb15368e7 user: olr tags: comunicate, fx
08:33
[fx] cancel code cosmetics check-in: 686c43591b user: olr tags: comunicate, fx
2018-11-12
12:22
[fx] minor coding style adjustments check-in: 74f2ec49cc user: olr tags: comunicate, fx
2018-11-07
09:04
[fr] nr: confusion date/datte, des/dès/dés check-in: 2528e7df7c user: olr tags: fr, trunk
2018-11-06
23:42
Added the possibility to web page script open gcpanel or lexicographe check-in: 5c25db680b user: IllusionPerdu tags: comunicate
18:33
[fr] nr: confusions diverses check-in: 9b6a855c65 user: olr tags: fr, trunk
2018-11-05
21:29
[fr] nr: à vau-l’eau, confusion pécher/pêcher, golf/golfe, cœur/chœur check-in: 7ac6a5159e user: olr tags: fr, trunk

Added gc_lang/fr/webext/content_scripts/event.js version [072a12ec6a].































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// Injected script into web page

"use strict";


function uniqueID () {
    let nMin = Math.ceil(0);
    let nMax = Math.floor(9999999);
    return Date.now().toString(36) + "-" + (Math.floor(Math.random() * (nMax - nMin)) + nMin).toString(36);
}

// ! Ecoute des messages venant du content-script
let sBrowserURL;
document.addEventListener("GrammalecteToPage", function respListener (event) {
    //console.log(event);
    let oData = JSON.parse(event.detail);
    // Message envoyer dès que le script est injecté
    if (typeof oData.init !== "undefined") {
        sBrowserURL = oData.init;
    }
    if (typeof oData.tiny !== "undefined") {
        //console.log('Detect Tiny', oData.tiny);
        TinyIDInPage(oData.tiny);
    }
    //console.log("GrammalecteToPage", oData);
});

// ! Permet d'envoyer des message vers le content script
// Retourne un identifiant unique au cas ou si besoin
// La ID unique peut être util si on permet d'intérogé grammalecte sans zone
function sendToGrammalecte (oDataAction) {
    let oDataToSend = oDataAction;
    if (typeof oDataToSend.sActionId === "undefined") {
        oDataToSend.sActionId = uniqueID();
    }
    if (oDataAction.elm) {
        if (!oDataAction.elm.id) {
            oDataAction.elm.id = uniqueID();
        }
        oDataToSend.elm = oDataAction.elm.id;
    }
    //console.log('oDataToSend', oDataToSend);
    let eventGrammalecte = new CustomEvent("GrammalecteEvent", { detail: JSON.stringify(oDataToSend) });
    document.dispatchEvent(eventGrammalecte);
    return oDataToSend.sActionId;
}

// ! Envoie de l’information que l'injection est bien faite ;)
// (peut être lu aussi bien par la page web que le content script)
var customAPILoaded = new CustomEvent("GLInjectedScriptIsReady");
document.dispatchEvent(customAPILoaded);

// Gros Hack : Auto add a button in tinymce ;)

// Page to test v4 https://www.quackit.com/html/html_editors/tinymce_editor.cfm
// https://www.responsivefilemanager.com/demo.php

// Page to test v3 http://www.imathas.com/editordemo/demo.html

function TinyOnEditor (event, editor=null) {
    let xEditorAdd = editor || event.editor;
    //console.log(xEditorAdd);
    if (typeof xEditorAdd.settings.Grammalecte === "undefined") {
        let aBtn;
        let cPlugSep;
        let bIsAdded = false;
        if (tinyMCE.majorVersion >= 4) {
            cPlugSep = " ";
            aBtn = ["toolbar3", "toolbar2", "toolbar1", "toolbar"];
        } else if (tinyMCE.majorVersion >= 3) {
            cPlugSep = ",";
            aBtn = ["theme_advanced_buttons3", "theme_advanced_buttons2", "theme_advanced_buttons1", "theme_advanced_buttons1_add_before"];
        }

        let sBtn;
        let iBtn = 0;
        for (sBtn of aBtn) {
            if (!bIsAdded && (typeof xEditorAdd.settings[sBtn] !== "undefined" || iBtn == aBtn.length)) {
                bIsAdded = true;
                if (typeof xEditorAdd.settings[sBtn] !== "undefined" && xEditorAdd.settings[sBtn] !== "") {
                    xEditorAdd.settings[sBtn] = (xEditorAdd.settings[sBtn] + cPlugSep + "Grammalecte").trim();
                } else {
                    let m = /(.*)([0-9])/.exec(sBtn);
                    if (m.length === 3 && parseInt(m[2]) > 1 && xEditorAdd.settings[sBtn] === "") {
                        sBtn = m[1] + (parseInt(m[2]) - 1);
                        xEditorAdd.settings[sBtn] = (xEditorAdd.settings[sBtn] + cPlugSep + "Grammalecte").trim();
                    } else {
                        xEditorAdd.settings[sBtn] = "Grammalecte";
                    }
                }
            }
            iBtn++;
        }
        if (!bIsAdded) {
            //Valeur par defaut
            xEditorAdd.settings[sBtn] =
                "undo redo | styleselect | bold italic | alignleft" +
                " aligncenter alignright alignjustify | " +
                " bullist numlist outdent indent | link image" +
                " Grammalecte";
        }
        xEditorAdd.settings["Grammalecte"] = true;
    }

    xEditorAdd.addButton("Grammalecte", {
        text: "",
        icon: false,
        image: sBrowserURL + "img/logo-16.png",
        //"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",
        onclick: function (e) {
            //console.log(xEditorAdd.getContent());
            //console.log(xEditorAdd.getBody().innerText);
            let sText = xEditorAdd.getBody().innerText;
            let iframeElement;
            if (typeof xEditorAdd.iframeElement !== "undefined" && typeof xEditorAdd.iframeElement.id !== "undefined") {
                iframeElement = xEditorAdd.iframeElement.id;
            } else if (typeof xEditorAdd.editorId !== "undefined") {
                iframeElement = xEditorAdd.editorId + "_ifr";
            }
            sendToGrammalecte({ sTextToParse: sText, iframe: iframeElement });
        }
    });
}

function TinyInPage () {
    for (let i = tinyMCE.editors.length - 1;  i > -1;  i--) {
        let sTinyId = tinyMCE.editors[i].id;
        if (typeof tinyMCE.editors[i].settings.Grammalecte === "undefined") {
            TinyIDInPage(sTinyId);
        }
    }
}

function TinyIDInPage (sTinyId) {
    if (tinyMCE.majorVersion >= 4) {
        tinyMCE.EditorManager.execCommand("mceFocus", true, sTinyId);
        tinyMCE.EditorManager.execCommand("mceRemoveEditor", true, sTinyId);
        tinyMCE.EditorManager.execCommand("mceAddEditor", false, sTinyId);
    } else if (tinyMCE.majorVersion >= 3) {
        tinyMCE.execCommand("mceFocus", false, sTinyId);
        tinyMCE.execCommand("mceRemoveControl", true, sTinyId);
        tinyMCE.execCommand("mceAddControl", false, sTinyId);
    }
}

if (typeof tinyMCE !== "undefined" && tinyMCE.majorVersion && tinyMCE.majorVersion >= 3 && tinyMCE.majorVersion <= 5) {
    //console.log("Have TinyMCE");
    if (tinyMCE.majorVersion >= 4) {
        tinyMCE.on("AddEditor", TinyOnEditor);
    } else if (tinyMCE.majorVersion >= 3) {
        tinyMCE.onAddEditor.add(TinyOnEditor);
    }
    try {
        TinyInPage();
    } catch (e) {
        console.error(e);
    }
}

/* // ! In the webpage script :
document.addEventListener('GLInjectedScriptIsReady', function() {
    // Le gestionnaire d'évènement est prêt!
    // La page web peut effectuer des actions
    ...
});
...
// Pour demander une correction sur le texte
sendToGrammalecte({"sTextToParse": "salut comment ca vaa?"});
// Pour demander une correction sur un élément html
sendToGrammalecte({"sTextToParse": true, "elm": elementHTML});
// Pour avoir le lexicographe sur un texte
sendToGrammalecte({"sTextForLexicographer": "salut comment ca vaa?"});
// Pour avoir le lexicographe sur un élément html
sendToGrammalecte({"sTextForLexicographer": true, "elm": elementHTML});
*/

Modified gc_lang/fr/webext/content_scripts/init.js from [31953bf9da] to [6855746abd].

9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
100
101
102
103
104
105
106













107
108
109



110
111
112





113
114
115
116















117
118
119
120
121
122
123
...
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
...
351
352
353
354
355
356
357































































































    Not possible to load content from within the extension:
    https://bugzilla.mozilla.org/show_bug.cgi?id=1267027
    No SharedWorker, no images allowed for now…
*/

"use strict";


function showError (e) {

    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/
let bChrome = false;
if (typeof(browser) !== "object") {
    var browser = chrome;
    bChrome = true;
}


/*
function loadImage (sContainerClass, sImagePath) {
    let xRequest = new XMLHttpRequest();
    xRequest.open('GET', browser.extension.getURL("")+sImagePath, false);
    xRequest.responseType = "arraybuffer";
    xRequest.send();
................................................................................
    img.src = (URL || webkitURL).createObjectURL(blobTxt); // webkitURL is obsolete: https://bugs.webkit.org/show_bug.cgi?id=167518
    Array.filter(document.getElementsByClassName(sContainerClass), function (oElem) {
        oElem.appendChild(img);
    });
}
*/



const oGrammalecte = {

    nMenu: 0,
    lMenu: [],

    oTFPanel: null,
    oLxgPanel: null,
    oGCPanel: null,

................................................................................
    xObserver: null,

    sExtensionUrl: 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) {
            this.xRightClickedNode = xEvent.target;
        }.bind(this), true);
    },

    clearRightClickedNode: function () {
        this.xRightClickedNode = null;
    },
................................................................................
        }
    },

    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,
................................................................................
    },

    createTFPanel: function () {
        if (this.oTFPanel === null) {
            this.oTFPanel = new GrammalecteTextFormatter("grammalecte_tf_panel", "Formateur de texte", 760, 615, false);
            //this.oTFPanel.logInnerHTML();
            this.oTFPanel.insertIntoPage();
            window.setTimeout(function(self){
                self.oTFPanel.adjustHeight();
            }, 50, this);
        }
    },

    createLxgPanel: function () {
        if (this.oLxgPanel === null) {
................................................................................
            Object.assign(xNode, {
                rel: "stylesheet",
                type: "text/css",
                media: "all",
                href: this.sExtensionUrl + sLinkCss
            });
            if (sLinkId) {
                Object.assign(xNode, {id: sLinkId});
            }
            if (xNodeToAppendTo) {
                xNodeToAppendTo.appendChild(xNode);
            }
            return xNode;
        }
        catch (e) {
            showError(e);
        }
    }
};


/*
    Connexion to the background
*/
let xGrammalectePort = browser.runtime.connect({name: "content-script port"});

xGrammalectePort.onMessage.addListener(function (oMessage) {
    let {sActionDone, result, dInfo, bEnd, bError} = oMessage;
    let sText = "";
    switch (sActionDone) {
        case "init":
            oGrammalecte.sExtensionUrl = oMessage.sUrl;
            // Start
            oGrammalecte.listenRightClick();
            oGrammalecte.createMenus();
................................................................................
            Commands received from the context menu
            (Context menu are initialized in background)
        */
        // Grammar checker commands
        case "rightClickGCEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                oGrammalecte.startGCPanel(oGrammalecte.xRightClickedNode);
                sText = (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.innerText;
                xGrammalectePort.postMessage({
                    sCommand: "parseAndSpellcheck",
                    dParam: {sText: sText, sCountry: "FR", bDebug: false, bContext: false},
                    dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id}
                });
            } else {
                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({
                sCommand: "parseAndSpellcheck",
                dParam: {sText: oGrammalecte.getPageText(), sCountry: "FR", bDebug: false, bContext: false},
                dInfo: {}
            });
            break;
        case "rightClickGCSelectedText":
            oGrammalecte.startGCPanel();
            // selected text is sent to the GC worker in the background script.
            break;
        // Lexicographer commands
        case "rightClickLxgEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                oGrammalecte.startLxgPanel();
                sText = (oGrammalecte.xRightClickedNode.tagName == "TEXTAREA") ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.innerText;
                xGrammalectePort.postMessage({
                    sCommand: "getListOfTokens",
                    dParam: {sText: sText},
                    dInfo: {sTextAreaId: oGrammalecte.xRightClickedNode.id}
                });
            } else {
                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({
                sCommand: "getListOfTokens",
                dParam: {sText: oGrammalecte.getPageText()},
                dInfo: {}
            });
            break;
        case "rightClickLxgSelectedText":
            oGrammalecte.startLxgPanel();
            // selected text is sent to the GC worker in the background script.
            break;
................................................................................
        case "rescanPage":
            oGrammalecte.rescanPage();
            break;
        default:
            console.log("[Content script] Unknown command: " + sActionDone);
    }
});






































































































<

>






|



<







 







>


<







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>


|
>
>
>
|
|

>
>
>
>
>
|
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|












<



|


|







 







|


|
|









|











|


|
|









|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
..
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
    Not possible to load content from within the extension:
    https://bugzilla.mozilla.org/show_bug.cgi?id=1267027
    No SharedWorker, no images allowed for now…
*/

"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/
let bChrome = false;
if (typeof browser !== "object") {
    var browser = chrome;
    bChrome = true;
}


/*
function loadImage (sContainerClass, sImagePath) {
    let xRequest = new XMLHttpRequest();
    xRequest.open('GET', browser.extension.getURL("")+sImagePath, false);
    xRequest.responseType = "arraybuffer";
    xRequest.send();
................................................................................
    img.src = (URL || webkitURL).createObjectURL(blobTxt); // webkitURL is obsolete: https://bugs.webkit.org/show_bug.cgi?id=167518
    Array.filter(document.getElementsByClassName(sContainerClass), function (oElem) {
        oElem.appendChild(img);
    });
}
*/

let oTinyAdd = {};

const oGrammalecte = {

    nMenu: 0,
    lMenu: [],

    oTFPanel: null,
    oLxgPanel: null,
    oGCPanel: null,

................................................................................
    xObserver: null,

    sExtensionUrl: 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) {
            this.xRightClickedNode = xEvent.target;
        }.bind(this), true);
    },

    clearRightClickedNode: function () {
        this.xRightClickedNode = null;
    },
................................................................................
        }
    },

    observePage: function () {
        /*
            When a textarea is added via jascript we add the menu :)
        */
        function NodeTinyMCE (xNode) {
            let parentNode = xNode.parentNode; //mutation.target
            if (
                typeof xNode !== "undefined" &&
                typeof xNode.id !== "undefined" &&
                typeof oTinyAdd[xNode.id] === "undefined" &&
                (parentNode.classList.contains("mce-edit-area") || parentNode.classList.contains("mceIframeContainer"))
            ) {
                //console.log(oTinyAdd, xNode, parentNode, parentNode.classList);
                oTinyAdd[xNode.id] = true;
                sendToWebpage({ tiny: xNode.id.replace("_ifr", "") });
            }
        }
        this.xObserver = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                for (let i = 0; i < mutation.addedNodes.length; i++) {
                    let MutationNode = mutation.addedNodes[i];
                    let tagName = MutationNode.tagName;

                    if (tagName == "TEXTAREA") {
                        oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, MutationNode));
                        oGrammalecte.nMenu += 1;
                    } else if (tagName == "IFRAME") {
                        NodeTinyMCE(MutationNode);
                    } else if ((tagName == "DIV" || tagName == "SPAN") && MutationNode.hasAttribute && MutationNode.hasAttribute("contenteditable")) {
                        oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, MutationNode));
                        oGrammalecte.nMenu += 1;
                    } else if (MutationNode.getElementsByTagName) {
                        for (let xNode of MutationNode.getElementsByTagName("textarea")) {
                            oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
                            oGrammalecte.nMenu += 1;
                        }
                        for (let xNode of MutationNode.getElementsByTagName("div")) {
                            if (xNode.hasAttribute && xNode.hasAttribute("contenteditable")){
                                oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
                                oGrammalecte.nMenu += 1;
                            }
                        }
                        for (let xNode of MutationNode.getElementsByTagName("span")) {
                            if (xNode.hasAttribute && xNode.hasAttribute("contenteditable")){
                                oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
                                oGrammalecte.nMenu += 1;
                            }
                        }
                        for (let xNode of MutationNode.getElementsByTagName("iframe")) {
                            NodeTinyMCE(xNode);
                        }
                    }
                }
            });
        });
        this.xObserver.observe(document.body, {
            childList: true,
................................................................................
    },

    createTFPanel: function () {
        if (this.oTFPanel === null) {
            this.oTFPanel = new GrammalecteTextFormatter("grammalecte_tf_panel", "Formateur de texte", 760, 615, false);
            //this.oTFPanel.logInnerHTML();
            this.oTFPanel.insertIntoPage();
            window.setTimeout(function(self) {
                self.oTFPanel.adjustHeight();
            }, 50, this);
        }
    },

    createLxgPanel: function () {
        if (this.oLxgPanel === null) {
................................................................................
            Object.assign(xNode, {
                rel: "stylesheet",
                type: "text/css",
                media: "all",
                href: this.sExtensionUrl + sLinkCss
            });
            if (sLinkId) {
                Object.assign(xNode, { id: sLinkId });
            }
            if (xNodeToAppendTo) {
                xNodeToAppendTo.appendChild(xNode);
            }
            return xNode;
        }
        catch (e) {
            showError(e);
        }
    }
};


/*
    Connexion to the background
*/
let xGrammalectePort = browser.runtime.connect({ name: "content-script port" });

xGrammalectePort.onMessage.addListener(function (oMessage) {
    let { sActionDone, result, dInfo, bEnd, bError } = oMessage;
    let sText = "";
    switch (sActionDone) {
        case "init":
            oGrammalecte.sExtensionUrl = oMessage.sUrl;
            // Start
            oGrammalecte.listenRightClick();
            oGrammalecte.createMenus();
................................................................................
            Commands received from the context menu
            (Context menu are initialized in background)
        */
        // Grammar checker commands
        case "rightClickGCEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                oGrammalecte.startGCPanel(oGrammalecte.xRightClickedNode);
                sText = oGrammalecte.xRightClickedNode.tagName == "TEXTAREA" ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.innerText;
                xGrammalectePort.postMessage({
                    sCommand: "parseAndSpellcheck",
                    dParam: { sText: sText, sCountry: "FR", bDebug: false, bContext: false },
                    dInfo: { sTextAreaId: oGrammalecte.xRightClickedNode.id }
                });
            } else {
                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({
                sCommand: "parseAndSpellcheck",
                dParam: { sText: oGrammalecte.getPageText(), sCountry: "FR", bDebug: false, bContext: false },
                dInfo: {}
            });
            break;
        case "rightClickGCSelectedText":
            oGrammalecte.startGCPanel();
            // selected text is sent to the GC worker in the background script.
            break;
        // Lexicographer commands
        case "rightClickLxgEditableNode":
            if (oGrammalecte.xRightClickedNode !== null) {
                oGrammalecte.startLxgPanel();
                sText = oGrammalecte.xRightClickedNode.tagName == "TEXTAREA" ? oGrammalecte.xRightClickedNode.value : oGrammalecte.xRightClickedNode.innerText;
                xGrammalectePort.postMessage({
                    sCommand: "getListOfTokens",
                    dParam: { sText: sText },
                    dInfo: { sTextAreaId: oGrammalecte.xRightClickedNode.id }
                });
            } else {
                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({
                sCommand: "getListOfTokens",
                dParam: { sText: oGrammalecte.getPageText() },
                dInfo: {}
            });
            break;
        case "rightClickLxgSelectedText":
            oGrammalecte.startLxgPanel();
            // selected text is sent to the GC worker in the background script.
            break;
................................................................................
        case "rescanPage":
            oGrammalecte.rescanPage();
            break;
        default:
            console.log("[Content script] Unknown command: " + sActionDone);
    }
});


/*
    Communicate webpage script <=> WebExtension
    La méthode d’injection de ce script est importante !

    Pour que la page web puisse envoyer des infos au background
    Page web => Script injecté => Content script => Background
    Pour la réponse, ce sont les mêmes étapes en sens inverse.
*/
let xScriptNode = document.createElement("script");
xScriptNode.src = browser.extension.getURL("content_scripts/event.js");
document.documentElement.appendChild(xScriptNode);

let nMin = Math.ceil(0);
let nMax = Math.floor(9999999);
function uniqueID () {
    return Date.now().toString(36) + "-" + (Math.floor(Math.random() * (nMax - nMin)) + nMin).toString(36);
}

// ! Écoute des messages venant du script injecté
document.addEventListener("GrammalecteEvent", function (event) {
    let oActionFromPage = JSON.parse(event.detail);
    //console.log(event);
    let sText = false;
    let dInfo = {};
    let xNodeToParse = null;

    if (oActionFromPage.iframe) {
        xNodeToParse = document.getElementById(oActionFromPage.iframe).contentWindow.document.body;
    }
    if (oActionFromPage.elm) {
        xNodeToParse = document.getElementById(oActionFromPage.elm);
        sText = xNodeToParse.tagName == "TEXTAREA" ? xNodeToParse.value : xNodeToParse.innerText;
        dInfo = { sTextAreaId: xNodeToParse.id };
    }
    if (oActionFromPage.sTextToParse) {
        oGrammalecte.startGCPanel(xNodeToParse);
        xGrammalectePort.postMessage({
            sCommand: "parseAndSpellcheck",
            dParam: { sText: sText || oActionFromPage.sTextToParse, sCountry: "FR", bDebug: false, bContext: false },
            dInfo: dInfo
        });
    }
    if (oActionFromPage.sTextForLexicographer) {
        oGrammalecte.startLxgPanel();
        xGrammalectePort.postMessage({
            sCommand: "getListOfTokens",
            dParam: { sText: sText || oActionFromPage.sTextForLexicographer },
            dInfo: dInfo
        });
    }
});

let bInjectedScriptReady = false;
let lBufferMsg = [];

// ! Permet d’envoyer des messages vers le script injecté
// (peut aussi être lu par un script sur la page web)
function sendToWebpage (oDataAction) {
    let oDataToSend = oDataAction;
    if (typeof oDataToSend.sActionId === "undefined") {
        oDataToSend.sActionId = uniqueID();
    }
    if (oDataAction.elm) {
        if (!oDataAction.elm.id) {
            oDataAction.elm.id = uniqueID();
        }
        oDataToSend.elm = oDataAction.elm.id;
    }

    if (!bInjectedScriptReady) {
        lBufferMsg.push(oDataToSend);
    } else {
        //console.log('sendToWebpage', oDataToSend);
        let eventGrammalecte = new CustomEvent("GrammalecteToPage", { detail: JSON.stringify(oDataToSend) });
        document.dispatchEvent(eventGrammalecte);
    }

    return oDataToSend.sActionId;
}

// ! Les messages ne peuvent être envoyés qu’après l’injection du script
document.addEventListener("GLInjectedScriptIsReady", function () {
    //console.log("GLInjectedScriptIsReady EXT");
    bInjectedScriptReady = true;
    if (lBufferMsg.length > 0) {
        for (const oDataToSend of lBufferMsg) {
            let eventGrammalecte = new CustomEvent("GrammalecteToPage", { detail: JSON.stringify(oDataToSend) });
            document.dispatchEvent(eventGrammalecte);
        }
    }
});

sendToWebpage({ init: browser.extension.getURL("") });

Modified gc_lang/fr/webext/manifest.json from [756d794e19] to [6f106795b7].

110
111
112
113
114
115
116

117
118
119
120
121
122
123
    "grammalecte/graphspell/_dictionaries/fr-allvars.json",
    "grammalecte/graphspell/_dictionaries/fr-classic.json",
    "grammalecte/graphspell/_dictionaries/fr-reform.json",
    "grammalecte/fr/conj_data.json",
    "grammalecte/fr/mfsp_data.json",
    "grammalecte/fr/phonet_data.json",
    "grammalecte/fr/tests_data.json",

    "img/logo-16.png"
  ],

  "permissions": [
    "activeTab",
    "contextMenus",
    "downloads",







>







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
    "grammalecte/graphspell/_dictionaries/fr-allvars.json",
    "grammalecte/graphspell/_dictionaries/fr-classic.json",
    "grammalecte/graphspell/_dictionaries/fr-reform.json",
    "grammalecte/fr/conj_data.json",
    "grammalecte/fr/mfsp_data.json",
    "grammalecte/fr/phonet_data.json",
    "grammalecte/fr/tests_data.json",
    "content_scripts/event.js",
    "img/logo-16.png"
  ],

  "permissions": [
    "activeTab",
    "contextMenus",
    "downloads",