Grammalecte  Check-in [0a02475e6f]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:[fx] fix text formatter and adjustments, +code cleaning
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | fx
Files: files | file ages | folders
SHA3-256:0a02475e6ffdb87b758b7496fc2ba7b791e088d0a534b587e46ce55ee49fafa6
User & Date: olr 2019-05-04 16:31:48
Context
2019-05-04
16:47
[fx] text formatter: close even when no change check-in: 43be289176 user: olr tags: fx, trunk
16:31
[fx] fix text formatter and adjustments, +code cleaning check-in: 0a02475e6f user: olr tags: fx, trunk
14:17
[fx] small code cleaning check-in: ce039a8de4 user: olr tags: fx, trunk
Changes

Changes to gc_lang/fr/webext/content_scripts/init.js.

1
2
3
4
5
6
7
8
9
10
11
12
..
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
...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
...
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
// Modify page

/* jshint esversion:6, -W097 */
/* jslint esversion:6 */
/* global GrammalectePanel, GrammalecteMenu, GrammalecteTextFormatter, GrammalecteLexicographer, GrammalecteGrammarChecker, GrammalecteMessageBox, showError, MutationObserver, chrome, document, console */

/*
    JS sucks (again, and again, and again, and again…)
    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…
*/
................................................................................
        }, true);
    },

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

    createMenus: function () {
        if (bChrome) {
            browser.storage.local.get("ui_options", this._createMenus.bind(this));
            return;
        }
        browser.storage.local.get("ui_options").then(this._createMenus.bind(this), showError);
    },

    _createMenus: function (oOptions) {
        if (oOptions.hasOwnProperty("ui_options")) {
            this.oOptions = oOptions.ui_options;
            if (this.oOptions.textarea) {
                for (let xNode of document.getElementsByTagName("textarea")) {
                    if (xNode.style.display !== "none" && xNode.style.visibility !== "hidden" && xNode.getAttribute("spellcheck") !== "false") {
                        this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
                        this.nMenu += 1;
                    }
                }
            }
            if (this.oOptions.editablenode) {
                for (let xNode of document.querySelectorAll("[contenteditable]")) {
                    this.lMenu.push(new GrammalecteMenu(this.nMenu, xNode));
                    this.nMenu += 1;
                }
            }
        }
    },

    observePage: function () {
................................................................................
        //    When a textarea is added via jascript we add the menu
        let that = this;
        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") {
                        if (that.oOptions === null || that.oOptions.textarea) {
                            oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, mutation.addedNodes[i]));
                            oGrammalecte.nMenu += 1;
                        }
                    } else if (mutation.addedNodes[i].getElementsByTagName) {
                        if (that.oOptions === null || that.oOptions.textarea) {
                            for (let xNode of mutation.addedNodes[i].getElementsByTagName("textarea")) {
                                oGrammalecte.lMenu.push(new GrammalecteMenu(oGrammalecte.nMenu, xNode));
                                oGrammalecte.nMenu += 1;
                            }
                        }
                    }
                }
            });
        });
................................................................................
        //if (this.oLxgPanel !== null) { this.oLxgPanel.hide(); }
        if (this.oGCPanel !== null) { this.oGCPanel.hide(); }
        for (let oMenu of this.lMenu) {
            oMenu.deleteNodes();
        }
        this.lMenu.length = 0; // to clear an array
        this.listenRightClick();
        this.createMenus();
    },

    createTFPanel: function () {
        if (this.oTFPanel === null) {
            this.oTFPanel = new GrammalecteTextFormatter("grammalecte_tf_panel", "Formateur de texte", 760, 600, false);
            //this.oTFPanel.logInnerHTML();
            this.oTFPanel.insertIntoPage();
            window.setTimeout(function(self){
                self.oTFPanel.adjustHeight();
            }, 50, this);
        }
    },
................................................................................
        this.oGCPanel.clear();
        this.oGCPanel.show();
        this.oGCPanel.showEditor();
        this.oGCPanel.start(xNode);
        this.oGCPanel.startWaitIcon();
    },

    startLxgPanel: function () {
        this.createGCPanel();
        this.oGCPanel.clearLexicographer();
        this.oGCPanel.showLexicographer();
        this.oGCPanel.startWaitIcon();
    },

    startFTPanel: function (xNode=null) {
        this.createTFPanel();
        this.oTFPanel.start(xNode);
        this.oTFPanel.show();
    },

    showMessage: function (sMessage) {
        this.createMessageBox();
        this.oMessageBox.show();
        this.oMessageBox.setMessage(sMessage);
    },

    getPageText: function () {
................................................................................
xGrammalectePort.onMessage.addListener(function (oMessage) {
    let {sActionDone, result, dInfo, bEnd, bError} = oMessage;
    switch (sActionDone) {
        case "init":
            oGrammalecte.sExtensionUrl = oMessage.sUrl;
            // Start
            oGrammalecte.listenRightClick();
            oGrammalecte.createMenus();
            oGrammalecte.observePage();
            break;
        case "parseAndSpellcheck":
            if (!bEnd) {
                oGrammalecte.oGCPanel.addParagraphResult(result);
            } else {
                oGrammalecte.oGCPanel.stopWaitIcon();




|







 







|

|


|


|





|






|







 







|





|







 







|




|







 







<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







1
2
3
4
5
6
7
8
9
10
11
12
..
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
...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
...
171
172
173
174
175
176
177













178
179
180
181
182
183
184
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
// Modify page

/* jshint esversion:6, -W097 */
/* jslint esversion:6 */
/* global GrammalectePanel, GrammalecteButton, GrammalecteTextFormatter, GrammalecteLexicographer, GrammalecteGrammarChecker, GrammalecteMessageBox, showError, MutationObserver, chrome, document, console */

/*
    JS sucks (again, and again, and again, and again…)
    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…
*/
................................................................................
        }, true);
    },

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

    createButtons: function () {
        if (bChrome) {
            browser.storage.local.get("ui_options", this._createButtons.bind(this));
            return;
        }
        browser.storage.local.get("ui_options").then(this._createButtons.bind(this), showError);
    },

    _createButtons: function (oOptions) {
        if (oOptions.hasOwnProperty("ui_options")) {
            this.oOptions = oOptions.ui_options;
            if (this.oOptions.textarea) {
                for (let xNode of document.getElementsByTagName("textarea")) {
                    if (xNode.style.display !== "none" && xNode.style.visibility !== "hidden" && xNode.getAttribute("spellcheck") !== "false") {
                        this.lMenu.push(new GrammalecteButton(this.nMenu, xNode));
                        this.nMenu += 1;
                    }
                }
            }
            if (this.oOptions.editablenode) {
                for (let xNode of document.querySelectorAll("[contenteditable]")) {
                    this.lMenu.push(new GrammalecteButton(this.nMenu, xNode));
                    this.nMenu += 1;
                }
            }
        }
    },

    observePage: function () {
................................................................................
        //    When a textarea is added via jascript we add the menu
        let that = this;
        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") {
                        if (that.oOptions === null || that.oOptions.textarea) {
                            oGrammalecte.lMenu.push(new GrammalecteButton(oGrammalecte.nMenu, mutation.addedNodes[i]));
                            oGrammalecte.nMenu += 1;
                        }
                    } else if (mutation.addedNodes[i].getElementsByTagName) {
                        if (that.oOptions === null || that.oOptions.textarea) {
                            for (let xNode of mutation.addedNodes[i].getElementsByTagName("textarea")) {
                                oGrammalecte.lMenu.push(new GrammalecteButton(oGrammalecte.nMenu, xNode));
                                oGrammalecte.nMenu += 1;
                            }
                        }
                    }
                }
            });
        });
................................................................................
        //if (this.oLxgPanel !== null) { this.oLxgPanel.hide(); }
        if (this.oGCPanel !== null) { this.oGCPanel.hide(); }
        for (let oMenu of this.lMenu) {
            oMenu.deleteNodes();
        }
        this.lMenu.length = 0; // to clear an array
        this.listenRightClick();
        this.createButtons();
    },

    createTFPanel: function () {
        if (this.oTFPanel === null) {
            this.oTFPanel = new GrammalecteTextFormatter("grammalecte_tf_panel", "Formateur de texte", 760, 595, false);
            //this.oTFPanel.logInnerHTML();
            this.oTFPanel.insertIntoPage();
            window.setTimeout(function(self){
                self.oTFPanel.adjustHeight();
            }, 50, this);
        }
    },
................................................................................
        this.oGCPanel.clear();
        this.oGCPanel.show();
        this.oGCPanel.showEditor();
        this.oGCPanel.start(xNode);
        this.oGCPanel.startWaitIcon();
    },














    showMessage: function (sMessage) {
        this.createMessageBox();
        this.oMessageBox.show();
        this.oMessageBox.setMessage(sMessage);
    },

    getPageText: function () {
................................................................................
xGrammalectePort.onMessage.addListener(function (oMessage) {
    let {sActionDone, result, dInfo, bEnd, bError} = oMessage;
    switch (sActionDone) {
        case "init":
            oGrammalecte.sExtensionUrl = oMessage.sUrl;
            // Start
            oGrammalecte.listenRightClick();
            oGrammalecte.createButtons();
            oGrammalecte.observePage();
            break;
        case "parseAndSpellcheck":
            if (!bEnd) {
                oGrammalecte.oGCPanel.addParagraphResult(result);
            } else {
                oGrammalecte.oGCPanel.stopWaitIcon();

Changes to gc_lang/fr/webext/content_scripts/menu.js.

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* jshint esversion:6, -W097 */
/* jslint esversion:6 */
/* global oGrammalecte, xGrammalectePort, showError, window, document */

"use strict";


class GrammalecteMenu {

    constructor (nMenu, xNode) {
        this.xNode = xNode;
        this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
        this.xButton.onclick = () => {
            oGrammalecte.startGCPanel(this.xNode);
            xGrammalectePort.postMessage({







|







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* jshint esversion:6, -W097 */
/* jslint esversion:6 */
/* global oGrammalecte, xGrammalectePort, showError, window, document */

"use strict";


class GrammalecteButton {

    constructor (nMenu, xNode) {
        this.xNode = xNode;
        this.xButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_main_button", textContent: " "});
        this.xButton.onclick = () => {
            oGrammalecte.startGCPanel(this.xNode);
            xGrammalectePort.postMessage({

Changes to gc_lang/fr/webext/content_scripts/panel.js.

24
25
26
27
28
29
30

31
32
33
34
35
36
37
..
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
        } else {
            this.xParent = document;
        }

        this.xPanelBar = oGrammalecte.createNode("div", {className: "grammalecte_panel_bar"});
        this.xPanelContent = oGrammalecte.createNode("div", {className: "grammalecte_panel_content"});
        this.xWaitIcon = this._createWaitIcon();

        this.xPanel = this._createPanel(sTitle);
        this.center();
    }

    _createPanel (sTitle) {
        try {
            let xPanel = oGrammalecte.createNode("div", {id: this.sId, className: "grammalecte_panel"});
................................................................................
            xButtonLine.appendChild(this._createCopyButton());
        }
        xButtonLine.appendChild(this._createMoveButton("stickToTop", "⏶", "Coller en haut"));
        xButtonLine.appendChild(this._createMoveButton("stickToLeft", "⏴", "Coller à gauche"));
        xButtonLine.appendChild(this._createMoveButton("center", "•", "Centrer"));
        xButtonLine.appendChild(this._createMoveButton("stickToRight", "⏵", "Coller à droite"));
        xButtonLine.appendChild(this._createMoveButton("stickToBottom", "⏷", "Coller en bas"));

        xButtonLine.appendChild(this._createCloseButton());
        return xButtonLine;
    }

    _createWaitIcon () {
        let xWaitIcon = oGrammalecte.createNode("div", {className: "grammalecte_spinner"});
        return xWaitIcon;
    }







>







 







>
|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
        } else {
            this.xParent = document;
        }

        this.xPanelBar = oGrammalecte.createNode("div", {className: "grammalecte_panel_bar"});
        this.xPanelContent = oGrammalecte.createNode("div", {className: "grammalecte_panel_content"});
        this.xWaitIcon = this._createWaitIcon();
        this.xCloseButton = null;
        this.xPanel = this._createPanel(sTitle);
        this.center();
    }

    _createPanel (sTitle) {
        try {
            let xPanel = oGrammalecte.createNode("div", {id: this.sId, className: "grammalecte_panel"});
................................................................................
            xButtonLine.appendChild(this._createCopyButton());
        }
        xButtonLine.appendChild(this._createMoveButton("stickToTop", "⏶", "Coller en haut"));
        xButtonLine.appendChild(this._createMoveButton("stickToLeft", "⏴", "Coller à gauche"));
        xButtonLine.appendChild(this._createMoveButton("center", "•", "Centrer"));
        xButtonLine.appendChild(this._createMoveButton("stickToRight", "⏵", "Coller à droite"));
        xButtonLine.appendChild(this._createMoveButton("stickToBottom", "⏷", "Coller en bas"));
        this.xCloseButton = this._createCloseButton();
        xButtonLine.appendChild(this.xCloseButton);
        return xButtonLine;
    }

    _createWaitIcon () {
        let xWaitIcon = oGrammalecte.createNode("div", {className: "grammalecte_spinner"});
        return xWaitIcon;
    }

Changes to gc_lang/fr/webext/content_scripts/panel_gc.js.

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
...
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
        this.xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Formateur de texte"});
        this.xEditorButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Éditeur"});
        this.xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Lexicographe"});
        this.xConjButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Conjugueur "});
        this.xLEButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Éditeur lexical "});
        this.xTFButton.onclick = () => {
            oGrammalecte.createTFPanel();
            if (this.xNode) {
                oGrammalecte.oTFPanel.start(this.xNode);
                oGrammalecte.oTFPanel.show();
                this.start(this.xNode);
                this.startWaitIcon();
                xGrammalectePort.postMessage({
                    sCommand: "parseAndSpellcheck",
                    dParam: {sText: this.getParsedText(), sCountry: "FR", bDebug: false, bContext: false},
                    dInfo: ((this.xNode) ? {sTextAreaId: this.xNode.id} : {})
                });
            } else {
                oGrammalecte.showMessage("Aucun node sur lequel appliquer le formatage de texte.")

            }
        };
        this.xEditorButton.onclick = () => {
            this.showEditor();
        };
        this.xLxgButton.onclick = () => {
            this.showLexicographer();
................................................................................
        this.xMenu.appendChild(this.xLxgButton)
        this.xMenu.appendChild(this.xConjButton)
        this.xMenu.appendChild(this.xLEButton)
        this.xPanelBar.appendChild(this.xMenu);
    }

    start (xNode=null) {

        this.oTooltip.hide();
        this.clear();
        this.xNode = xNode;
        if (xNode) {
            this.oNodeControl.setNode(xNode);
            if (!(xNode.tagName == "TEXTAREA" || xNode.tagName == "INPUT")) {
                this.addMessage("Note : cette zone de texte n’est pas un champ de formulaire “textarea” mais un node HTML éditable. Une telle zone de texte est susceptible de contenir des éléments non textuels qui seront effacés lors de la correction.");
            }
        }
    }












    getParsedText () {
        if (this.xNode) {
            return (this.xNode.tagName == "TEXTAREA") ? this.xNode.value.normalize("NFC") : this.xNode.innerText.normalize("NFC");
        } else {
            return oGrammalecte.getPageText();
        }
    }

    showEditor () {
        this.xGCPanelContent.style.display = "block";







|
|

<
<
<
<
<
<
<

<
>







 







>


<







>
>
>
>
>
>
>
>
>
>
>



|







71
72
73
74
75
76
77
78
79
80







81

82
83
84
85
86
87
88
89
...
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
        this.xTFButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Formateur de texte"});
        this.xEditorButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Éditeur"});
        this.xLxgButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Lexicographe"});
        this.xConjButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Conjugueur "});
        this.xLEButton = oGrammalecte.createNode("div", {className: "grammalecte_menu_button", textContent: "Éditeur lexical "});
        this.xTFButton.onclick = () => {
            oGrammalecte.createTFPanel();
            if (this.xNode  && (this.xNode.tagName == "TEXTAREA" || this.xNode.tagName == "INPUT" || this.xNode.isContentEditable)) {
                oGrammalecte.oTFPanel.start(this);
                oGrammalecte.oTFPanel.show();







            } else {

                oGrammalecte.showMessage("Aucune zone de texte éditable sur laquelle appliquer le formatage de texte.")
            }
        };
        this.xEditorButton.onclick = () => {
            this.showEditor();
        };
        this.xLxgButton.onclick = () => {
            this.showLexicographer();
................................................................................
        this.xMenu.appendChild(this.xLxgButton)
        this.xMenu.appendChild(this.xConjButton)
        this.xMenu.appendChild(this.xLEButton)
        this.xPanelBar.appendChild(this.xMenu);
    }

    start (xNode=null) {
        this.xNode = xNode;
        this.oTooltip.hide();
        this.clear();

        if (xNode) {
            this.oNodeControl.setNode(xNode);
            if (!(xNode.tagName == "TEXTAREA" || xNode.tagName == "INPUT")) {
                this.addMessage("Note : cette zone de texte n’est pas un champ de formulaire “textarea” mais un node HTML éditable. Une telle zone de texte est susceptible de contenir des éléments non textuels qui seront effacés lors de la correction.");
            }
        }
    }

    recheckAll () {
        this.oTooltip.hide();
        this.clear();
        this.startWaitIcon();
        xGrammalectePort.postMessage({
            sCommand: "parseAndSpellcheck",
            dParam: {sText: this.getParsedText(), sCountry: "FR", bDebug: false, bContext: false},
            dInfo: ((this.xNode) ? {sTextAreaId: this.xNode.id} : {})
        });
    }

    getParsedText () {
        if (this.xNode) {
            return (this.xNode.tagName == "TEXTAREA" || this.xNode.tagName == "INPUT") ? this.xNode.value.normalize("NFC") : this.xNode.innerText.normalize("NFC");
        } else {
            return oGrammalecte.getPageText();
        }
    }

    showEditor () {
        this.xGCPanelContent.style.display = "block";

Changes to gc_lang/fr/webext/content_scripts/panel_tf.js.

10
11
12
13
14
15
16
17
18

19
20
21
22
23
24








25
26
27
28
29
30
31
...
170
171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187













188
189
190
191
192
193
194
...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

class GrammalecteTextFormatter extends GrammalectePanel {

    constructor (...args) {
        super(...args);
        this.xTFNode = this._createTextFormatter();
        this.xPanelContent.appendChild(this.xTFNode);
        this.xTextArea = null;
        this.xPanel.style.zIndex = 2147483647; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */


        this.TextFormatter = new TextFormatter();
        this.formatText = this.TextFormatter.formatTextRuleCount;
        this.removeHyphenAtEndOfParagraphs = this.TextFormatter.removeHyphenAtEndOfParagraphsCount;
        this.mergeContiguousParagraphs = this.TextFormatter.mergeContiguousParagraphsCount;
        this.getParagraph = this.TextFormatter.getParagraph;








    }

    _createTextFormatter () {
        let xTFNode = document.createElement("div");
        try {
            // Options
            let xOptions = oGrammalecte.createNode("div", {id: "grammalecte_tf_options"});
................................................................................
        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"}));
        return xLine;
    }

    /*
        Actions
    */
    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 (this.xParent.getElementById(sOptName).dataset.selected == "true") {
            this.xParent.getElementById(sOptName.slice(2)).style.opacity = 1;
        } else {
            this.xParent.getElementById(sOptName.slice(2)).style.opacity = 0.3;
        }
................................................................................
    }

    apply () {
        try {
            const t0 = Date.now();
            //window.setCursor("wait"); // change pointer
            this.resetProgressBar();
            let sText = this.xTextArea.value.normalize("NFC");
            this.xParent.getElementById('grammalecte_tf_progressbar').max = 7;
            let n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0, n7 = 0;

            // Restructuration
            if (this.isSelected("o_group_struct")) {
                if (this.isSelected("o_remove_hyphens_at_end_of_paragraphs")) {
                    [sText, n1] = this.removeHyphenAtEndOfParagraphs(sText);
................................................................................
            this.xParent.getElementById('grammalecte_tf_progressbar').value = this.xParent.getElementById('grammalecte_tf_progressbar').max;
            // end of processing

            //window.setCursor("auto"); // restore pointer

            const t1 = Date.now();
            this.xParent.getElementById('grammalecte_tf_time_res').textContent = this.getTimeRes((t1-t0)/1000);
            this.xTextArea.value = sText;
        }
        catch (e) {
            showError(e);
        }
    }

    getTimeRes (n) {







|

>






>
>
>
>
>
>
>
>







 







|
|
|
>








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







 







|







 







|







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
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551

class GrammalecteTextFormatter extends GrammalectePanel {

    constructor (...args) {
        super(...args);
        this.xTFNode = this._createTextFormatter();
        this.xPanelContent.appendChild(this.xTFNode);
        this.xTextNode = null;
        this.xPanel.style.zIndex = 2147483647; /* maximum is 2147483647: https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index */
        this.bTextChanged = false;

        this.TextFormatter = new TextFormatter();
        this.formatText = this.TextFormatter.formatTextRuleCount;
        this.removeHyphenAtEndOfParagraphs = this.TextFormatter.removeHyphenAtEndOfParagraphsCount;
        this.mergeContiguousParagraphs = this.TextFormatter.mergeContiguousParagraphsCount;
        this.getParagraph = this.TextFormatter.getParagraph;

        this.xCloseButton.onclick = () => {
            if (this.bTextChanged) {
                // recheck text after modification
                this.xGCPanel.recheckAll();
                this.hide();
            }
        };
    }

    _createTextFormatter () {
        let xTFNode = document.createElement("div");
        try {
            // Options
            let xOptions = oGrammalecte.createNode("div", {id: "grammalecte_tf_options"});
................................................................................
        xLine.appendChild(oGrammalecte.createNode("div", {id: "res_"+"o_ordinals_no_exponant", className: "grammalecte_tf_result", textContent: "·"}));
        return xLine;
    }

    /*
        Actions
    */
    start (xGCPanel) {
        if (xGCPanel.xNode !== null && (xGCPanel.xNode.tagName == "TEXTAREA" || xGCPanel.xNode.tagName == "INPUT" || xGCPanel.xNode.isContentEditable)) {
            this.xTextNode = xGCPanel.xNode;
            this.xGCPanel = xGCPanel;
            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));
            }
        }
    }

    getNodeText () {
        return (this.xTextNode.tagName == "TEXTAREA" || this.xTextNode.tagName == "INPUT") ? this.xTextNode.value.normalize("NFC") : this.xTextNode.innerText.normalize("NFC");
    }

    setNodeText (sText) {
        if (this.xTextNode.tagName == "TEXTAREA" || this.xTextNode.tagName == "INPUT") {
            this.xTextNode.value = sText;
        } else {
            this.xTextNode.textContent = sText;
        }
        this.bTextChanged = true;
    }

    switchGroup (sOptName) {
        if (this.xParent.getElementById(sOptName).dataset.selected == "true") {
            this.xParent.getElementById(sOptName.slice(2)).style.opacity = 1;
        } else {
            this.xParent.getElementById(sOptName.slice(2)).style.opacity = 0.3;
        }
................................................................................
    }

    apply () {
        try {
            const t0 = Date.now();
            //window.setCursor("wait"); // change pointer
            this.resetProgressBar();
            let sText = this.getNodeText();
            this.xParent.getElementById('grammalecte_tf_progressbar').max = 7;
            let n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0, n7 = 0;

            // Restructuration
            if (this.isSelected("o_group_struct")) {
                if (this.isSelected("o_remove_hyphens_at_end_of_paragraphs")) {
                    [sText, n1] = this.removeHyphenAtEndOfParagraphs(sText);
................................................................................
            this.xParent.getElementById('grammalecte_tf_progressbar').value = this.xParent.getElementById('grammalecte_tf_progressbar').max;
            // end of processing

            //window.setCursor("auto"); // restore pointer

            const t1 = Date.now();
            this.xParent.getElementById('grammalecte_tf_time_res').textContent = this.getTimeRes((t1-t0)/1000);
            this.setNodeText(sText);
        }
        catch (e) {
            showError(e);
        }
    }

    getTimeRes (n) {

Changes to gc_lang/fr/webext/manifest.json.

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
      ],
      "run_at": "document_idle"
    }
  ],

  "commands": {
    "grammar_checker": {
      "suggested_key": { "default": "Ctrl+Shift+Z" },
      "description": "Ouvre le correcteur grammatical"
    },
    "conjugueur_tab": {
      "suggested_key": { "default": "Ctrl+Shift+6" },
      "description": "Ouvre le conjugueur"
    },
    "lexicon_editor": {







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
      ],
      "run_at": "document_idle"
    }
  ],

  "commands": {
    "grammar_checker": {
      "suggested_key": { "default": "Ctrl+Shift+F" },
      "description": "Ouvre le correcteur grammatical"
    },
    "conjugueur_tab": {
      "suggested_key": { "default": "Ctrl+Shift+6" },
      "description": "Ouvre le conjugueur"
    },
    "lexicon_editor": {

Changes to gc_lang/fr/webext/panel/main.html.

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
              <p class="option_description">Ces zones de texte sont les champs de formulaire usuels pour saisir du texte. Ils ne permettent que la saisie de texte brut, sans fioritures.</p>
          </div>
          <div class="option_section" id="ui_option_editablenode_box">
              <p><input type="checkbox" id="ui_option_editablenode" /> <label for="ui_option_editablenode">“Nodes” éditables</label></p>
              <p class="option_description">Ces zones de texte sont des sections de page web éditables. Il est fréquent que ces zones de texte apparaissent comme des “textareas” standard. Il est aussi fréquent que ces zones de texte soient couplées avec toutes sortes de logiciels (de simples scripts d’aide à la mise en page ou des applications complexes). Ces zones de texte permettent l’affichage de texte enrichi (italique, gras, hyperlien, images, etc.).</p>
          </div>
          <h2>Raccourcis clavier</h2>
          <p class="shortcut">CTRL+MAJ+Z</p>
          <p class="shortcut_label">Correcteur grammatical</p>
          <p class="shortcut">CTRL+MAJ+6</p>
          <p class="shortcut_label">Conjugueur</p>
          <p class="shortcut">CTRL+MAJ+7</p>
          <p class="shortcut_label">Éditeur lexical</p>
          <!--<p class="shortcut">CTRL+MAJ+8</p>
          <p class="shortcut_label">Dictionnaires communautaires</p>-->







|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
              <p class="option_description">Ces zones de texte sont les champs de formulaire usuels pour saisir du texte. Ils ne permettent que la saisie de texte brut, sans fioritures.</p>
          </div>
          <div class="option_section" id="ui_option_editablenode_box">
              <p><input type="checkbox" id="ui_option_editablenode" /> <label for="ui_option_editablenode">“Nodes” éditables</label></p>
              <p class="option_description">Ces zones de texte sont des sections de page web éditables. Il est fréquent que ces zones de texte apparaissent comme des “textareas” standard. Il est aussi fréquent que ces zones de texte soient couplées avec toutes sortes de logiciels (de simples scripts d’aide à la mise en page ou des applications complexes). Ces zones de texte permettent l’affichage de texte enrichi (italique, gras, hyperlien, images, etc.).</p>
          </div>
          <h2>Raccourcis clavier</h2>
          <p class="shortcut">CTRL+MAJ+F</p>
          <p class="shortcut_label">Correcteur grammatical</p>
          <p class="shortcut">CTRL+MAJ+6</p>
          <p class="shortcut_label">Conjugueur</p>
          <p class="shortcut">CTRL+MAJ+7</p>
          <p class="shortcut_label">Éditeur lexical</p>
          <!--<p class="shortcut">CTRL+MAJ+8</p>
          <p class="shortcut_label">Dictionnaires communautaires</p>-->