Grammalecte  Check-in [e4791e17bb]

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

Overview
Comment:[fx] gc panel: CSS adjustements and auto-refresh adjustements
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | fx
Files: files | file ages | folders
SHA3-256:e4791e17bb2802d8a6bb9bb5252ca2685591d260f0314e4f0b3fdde1ade71336
User & Date: olr 2019-05-20 12:18:15
Context
2019-05-20
13:22
[fx] gc panel: refresh with blur event (not a so good idea?) check-in: e1f9580c26 user: olr tags: fx, trunk
12:18
[fx] gc panel: CSS adjustements and auto-refresh adjustements check-in: e4791e17bb user: olr tags: fx, trunk
08:40
[fx] gc panel: set size and position update check-in: a0ef5bac85 user: olr tags: fx, trunk
Changes

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

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
    font-size: 14px;
    font-weight: bold;
    text-align: center;
    cursor: pointer;
}
div.grammalecte_copy_button {
    border-radius: 2px;
    color: hsla(210, 0%, 100%, .5);
    margin-right: 10px;
}
div.grammalecte_copy_button:hover {
    background-color: hsl(210, 90%, 35%, .5);
    color: hsla(210, 0%, 100%, 1);
}
div.grammalecte_move_button {
    padding: 1px 5px;
    border-radius: 16px;
    color: hsl(180, 0%, 100%);
    opacity: .5;
}
div.grammalecte_move_button_changeWidth {
    padding: 3px 5px;

}
div.grammalecte_move_button_changeHeight {
    padding: 3px 5px;
    margin-right: 10px;

}
div.grammalecte_move_button_center {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><circle fill="%23fff" cx="6" cy="6" r="4"/></svg>') ;
}
div.grammalecte_move_button_up {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 6,2 6,6 h -12"/></svg>');
}
div.grammalecte_move_button_right {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 2,0 6,6 -6,6"/></svg>');
}
div.grammalecte_move_button_down {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 0,2 6,6 6,-6"/></svg>');
}
div.grammalecte_move_button_left {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 2,6 6,6 v -12"/></svg>');
}
div.grammalecte_move_button:hover {
    background-color: hsla(180, 80%, 50%, .2);







|



|






|


|
>


|

>











|



|







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
    font-size: 14px;
    font-weight: bold;
    text-align: center;
    cursor: pointer;
}
div.grammalecte_copy_button {
    border-radius: 2px;
    color: hsla(210, 0%, 100%, .4);
    margin-right: 10px;
}
div.grammalecte_copy_button:hover {
    background-color: hsl(210, 50%, 55%);
    color: hsla(210, 0%, 100%, 1);
}
div.grammalecte_move_button {
    padding: 1px 5px;
    border-radius: 16px;
    color: hsl(180, 0%, 100%);
    opacity: .2;
}
div.grammalecte_move_button_changeWidth {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 6,2 4,4 -4,4"/><path fill="%23fff" d="m 0,6 4,4 v -8"/></svg>');
}
div.grammalecte_move_button_changeHeight {
    padding: 1px 10px;
    margin-right: 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 6,0 4,4 h -8"/><path fill="%23fff" d="m 2,6 4,4 4,-4"/></svg>');
}
div.grammalecte_move_button_center {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><circle fill="%23fff" cx="6" cy="6" r="4"/></svg>') ;
}
div.grammalecte_move_button_up {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 6,2 6,6 h -12"/></svg>');
}
div.grammalecte_move_button_right {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 4,0 6,6 -6,6"/></svg>');
}
div.grammalecte_move_button_down {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 0,4 6,6 6,-6"/></svg>');
}
div.grammalecte_move_button_left {
    padding: 1px 10px;
    background: center no-repeat url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path fill="%23fff" d="m 2,6 6,6 v -12"/></svg>');
}
div.grammalecte_move_button:hover {
    background-color: hsla(180, 80%, 50%, .2);

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

64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
        return xImg;
    }

    _createButtons () {
        let xButtonLine = oGrammalecte.createNode("div", {className: "grammalecte_panel_commands"});
        xButtonLine.appendChild(this.xWaitIcon);
        if (this.sId === "grammalecte_gc_panel") {

            xButtonLine.appendChild(this._createCopyButton());
        }
        if (this.bFlexible) {
            this.xWidthButton = this._createMoveButton("changeWidth", "L", "Étendre en largeur");
            this.xHeightButton = this._createMoveButton("changeHeight", "H", "Étendre en hauteur");
            xButtonLine.appendChild(this.xWidthButton);
            xButtonLine.appendChild(this.xHeightButton);
        }
        xButtonLine.appendChild(this._createMoveButton("up", " ", "Monter")); // use char ⏶ when Windows 10 be vast majority of OS (Trebuchet MS not updated on other OS)
        xButtonLine.appendChild(this._createMoveButton("left", " ", "À gauche")); // use char ⏴ when Windows 10 be vast majority of OS (Trebuchet MS not updated on other OS)
        xButtonLine.appendChild(this._createMoveButton("center", " ", "Centrer")); // char • can be used already
        xButtonLine.appendChild(this._createMoveButton("right", " ", "À droite")); // use char ⏵ when Windows 10 be vast majority of OS (Trebuchet MS not updated on other OS)
................................................................................
        this.bVertStrech = !this.bVertStrech;
        this.setSizeAndPosition();
    }

    setSizeAndPosition () {
        // size
        if (this.xWidthButton && this.xHeightButton) {
            this.xWidthButton.style.opacity = (this.bHorizStrech) ? .9 : .5;
            this.xHeightButton.style.opacity = (this.bVertStrech) ? .9 : .5;
        }
        let nWidth = Math.min(this.nWidth, window.innerWidth-200);
        let nHeight = ([4, 5, 6].includes(this.nPosition)) ? Math.min(this.nHeight, window.innerHeight-100) : Math.floor(window.innerHeight*0.45);
        if (this.bFlexible) {
            if (this.bHorizStrech) {
                nWidth = Math.min(this.nWidth*1.33, window.innerWidth-200);
            }







>
|


|
|







 







|
|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
        return xImg;
    }

    _createButtons () {
        let xButtonLine = oGrammalecte.createNode("div", {className: "grammalecte_panel_commands"});
        xButtonLine.appendChild(this.xWaitIcon);
        if (this.sId === "grammalecte_gc_panel") {
            this.xClipboardButton = this._createCopyButton();
            xButtonLine.appendChild(this.xClipboardButton);
        }
        if (this.bFlexible) {
            this.xWidthButton = this._createMoveButton("changeWidth", " ", "Étendre en largeur");
            this.xHeightButton = this._createMoveButton("changeHeight", " ", "Étendre en hauteur");
            xButtonLine.appendChild(this.xWidthButton);
            xButtonLine.appendChild(this.xHeightButton);
        }
        xButtonLine.appendChild(this._createMoveButton("up", " ", "Monter")); // use char ⏶ when Windows 10 be vast majority of OS (Trebuchet MS not updated on other OS)
        xButtonLine.appendChild(this._createMoveButton("left", " ", "À gauche")); // use char ⏴ when Windows 10 be vast majority of OS (Trebuchet MS not updated on other OS)
        xButtonLine.appendChild(this._createMoveButton("center", " ", "Centrer")); // char • can be used already
        xButtonLine.appendChild(this._createMoveButton("right", " ", "À droite")); // use char ⏵ when Windows 10 be vast majority of OS (Trebuchet MS not updated on other OS)
................................................................................
        this.bVertStrech = !this.bVertStrech;
        this.setSizeAndPosition();
    }

    setSizeAndPosition () {
        // size
        if (this.xWidthButton && this.xHeightButton) {
            this.xWidthButton.style.opacity = (this.bHorizStrech) ? ".9" : "";
            this.xHeightButton.style.opacity = (this.bVertStrech) ? ".9" : "";
        }
        let nWidth = Math.min(this.nWidth, window.innerWidth-200);
        let nHeight = ([4, 5, 6].includes(this.nPosition)) ? Math.min(this.nHeight, window.innerHeight-100) : Math.floor(window.innerHeight*0.45);
        if (this.bFlexible) {
            if (this.bHorizStrech) {
                nWidth = Math.min(this.nWidth*1.33, window.innerWidth-200);
            }

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

213
214
215
216
217
218
219

220
221

222
223
224

225
226
227










228
229
230
231
232
233
234
...
331
332
333
334
335
336
337

338
339
340

341
342
343
344
345
346
347
...
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
                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "↻", title: "Réanalyser…"}, {para_num: oResult.iParaNum}));
                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", title: "Cacher", style: "font-weight: bold;"}));
                // paragraph
                let xParagraph = oGrammalecte.createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum});
                xParagraph.setAttribute("spellcheck", "false"); // doesn’t seem possible to use “spellcheck” as a common attribute.
                xParagraph.dataset.timer_id = "0";
                xParagraph.addEventListener("input", function (xEvent) {

                    window.clearTimeout(parseInt(xParagraph.dataset.timer_id));
                    xParagraph.dataset.timer_id = window.setTimeout(this.recheckParagraph.bind(this), 3000, oResult.iParaNum);

                    let [nStart, nEnd] = oGrammalecte.getCaretPosition(xParagraph);
                    xParagraph.dataset.caret_position_start = nStart;
                    xParagraph.dataset.caret_position_end = nEnd;

                    this.oTextControl.setParagraph(parseInt(xEvent.target.dataset.para_num), this.purgeText(xEvent.target.textContent));
                    this.oTextControl.write();
                }.bind(this)










                , true);
                this._tagParagraph(xParagraph, oResult.sParagraph, oResult.iParaNum, oResult.aGrammErr, oResult.aSpellErr);
                // creation
                xNodeDiv.appendChild(xActionsBar);
                xNodeDiv.appendChild(xParagraph);
                this.xParagraphList.appendChild(xNodeDiv);
            }
................................................................................
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.backgroundColor = "hsl(0, 50%, 50%)";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.boxShadow = "0 0 0 3px hsla(0, 0%, 50%, .2)";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.animation = "grammalecte-pulse 1s linear infinite";
    }

    freeParagraph (xParagraph) {
        xParagraph.contentEditable = "true";

        let nStart = parseInt(xParagraph.dataset.caret_position_start);
        let nEnd = parseInt(xParagraph.dataset.caret_position_end);
        oGrammalecte.setCaretPosition(xParagraph, nStart, nEnd);

        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).textContent = "↻";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.backgroundColor = "";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.animation = "";
        setTimeout(() => { this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.boxShadow = ""; }, 500);
    }

    applySuggestion (sNodeSuggId) { // sugg
................................................................................
        let xNode = oGrammalecte.createNode("div", {className: "grammalecte_panel_flow_message", textContent: sMessage});
        this.xParagraphList.appendChild(xNode);
    }

    copyTextToClipboard () {
        this.startWaitIcon();
        try {

            let sText = "";
            // Dans un shadow, <this.xParent.getElementsByClassName> n’existe pas.
            let xElem = this.xParent.getElementById("grammalecte_gc_panel");
            for (let xNode of xElem.getElementsByClassName("grammalecte_paragraph")) {
                sText += xNode.textContent + "\n";
            }
            this._sendTextToClipboard(sText);

        }
        catch (e) {
            showError(e);
        }
        this.stopWaitIcon();
    }

    _sendTextToClipboard (sText)  {
        let xClipboardButton = this.xParent.getElementById("grammalecte_clipboard_button");
        xClipboardButton.textContent = "⇒ presse-papiers";
        // Firefox 63+, Chrome 66+
        // Working draft: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard

        navigator.clipboard.writeText(sText)
        .then(
            (res) => { window.setTimeout(() => { xClipboardButton.textContent = "📋"; }, 2000); }
        )
        .catch(
            (e) => { console.error(e); this._sendTextToClipboard(sText, xClipboardButton); }
        );


    }


    _sendTextToClipboardFallback (sText, xClipboardButton) {
        try {
            // Copy to clipboard fallback
            // recipe from https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/clipboard-helper.js
            function setClipboardData (xEvent) {
                document.removeEventListener("copy", setClipboardData, true);
                xEvent.stopImmediatePropagation();
                xEvent.preventDefault();
                xEvent.clipboardData.setData("text/plain", sText);
            }
            document.addEventListener("copy", setClipboardData, true);
            document.execCommand("copy");
            window.setTimeout(() => { xClipboardButton.textContent = "📋"; }, 2000);
        }
        catch (e) {
            console.error(e);
        }
    }

    // Lexicographer







>


>



>



>
>
>
>
>
>
>
>
>
>







 







>
|
|
|
>







 







<







<








<
|


>
|
|
|
|
|
|
|
>
>
|
|
>
|











|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
...
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
                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_check" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_green", textContent: "↻", title: "Réanalyser…"}, {para_num: oResult.iParaNum}));
                xActionsBar.appendChild(oGrammalecte.createNode("div", {id: "grammalecte_hide" + oResult.iParaNum, className: "grammalecte_paragraph_button grammalecte_red", textContent: "×", title: "Cacher", style: "font-weight: bold;"}));
                // paragraph
                let xParagraph = oGrammalecte.createNode("p", {id: "grammalecte_paragraph"+oResult.iParaNum, className: "grammalecte_paragraph", lang: "fr", contentEditable: "true"}, {para_num: oResult.iParaNum});
                xParagraph.setAttribute("spellcheck", "false"); // doesn’t seem possible to use “spellcheck” as a common attribute.
                xParagraph.dataset.timer_id = "0";
                xParagraph.addEventListener("input", function (xEvent) {
                    // timer for refreshing analysis
                    window.clearTimeout(parseInt(xParagraph.dataset.timer_id));
                    xParagraph.dataset.timer_id = window.setTimeout(this.recheckParagraph.bind(this), 3000, oResult.iParaNum);
                    // save caret position
                    let [nStart, nEnd] = oGrammalecte.getCaretPosition(xParagraph);
                    xParagraph.dataset.caret_position_start = nStart;
                    xParagraph.dataset.caret_position_end = nEnd;
                    // write text
                    this.oTextControl.setParagraph(parseInt(xEvent.target.dataset.para_num), this.purgeText(xEvent.target.textContent));
                    this.oTextControl.write();
                }.bind(this)
                , true);
                xParagraph.addEventListener("blur", function (xEvent) {
                    // remove timer for refreshing analysis
                    window.clearTimeout(parseInt(xParagraph.dataset.timer_id));
                    // unset caret position
                    xParagraph.dataset.caret_position_start = "-1";
                    xParagraph.dataset.caret_position_end = "-1";
                    // recheck
                    this.recheckParagraph(oResult.iParaNum);
                }.bind(this)
                , true);
                this._tagParagraph(xParagraph, oResult.sParagraph, oResult.iParaNum, oResult.aGrammErr, oResult.aSpellErr);
                // creation
                xNodeDiv.appendChild(xActionsBar);
                xNodeDiv.appendChild(xParagraph);
                this.xParagraphList.appendChild(xNodeDiv);
            }
................................................................................
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.backgroundColor = "hsl(0, 50%, 50%)";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.boxShadow = "0 0 0 3px hsla(0, 0%, 50%, .2)";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.animation = "grammalecte-pulse 1s linear infinite";
    }

    freeParagraph (xParagraph) {
        xParagraph.contentEditable = "true";
        if (xParagraph.dataset.caret_position_start !== "-1") {
            let nStart = parseInt(xParagraph.dataset.caret_position_start);
            let nEnd = parseInt(xParagraph.dataset.caret_position_end);
            oGrammalecte.setCaretPosition(xParagraph, nStart, nEnd);
        }
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).textContent = "↻";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.backgroundColor = "";
        this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.animation = "";
        setTimeout(() => { this.xParent.getElementById("grammalecte_check"+xParagraph.dataset.para_num).style.boxShadow = ""; }, 500);
    }

    applySuggestion (sNodeSuggId) { // sugg
................................................................................
        let xNode = oGrammalecte.createNode("div", {className: "grammalecte_panel_flow_message", textContent: sMessage});
        this.xParagraphList.appendChild(xNode);
    }

    copyTextToClipboard () {
        this.startWaitIcon();
        try {

            let sText = "";
            // Dans un shadow, <this.xParent.getElementsByClassName> n’existe pas.
            let xElem = this.xParent.getElementById("grammalecte_gc_panel");
            for (let xNode of xElem.getElementsByClassName("grammalecte_paragraph")) {
                sText += xNode.textContent + "\n";
            }
            this._sendTextToClipboard(sText);

        }
        catch (e) {
            showError(e);
        }
        this.stopWaitIcon();
    }

    _sendTextToClipboard (sText)  {

        this.xClipboardButton.textContent = "⇒ presse-papiers";
        // Firefox 63+, Chrome 66+
        // Working draft: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard
        if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(sText)
            .then(
                (res) => { window.setTimeout(() => { this.xClipboardButton.textContent = "📋"; }, 2000); }
            )
            .catch(
                (e) => { console.error(e); this._sendTextToClipboard(sText); }
            );
        } else {
            this._sendTextToClipboardFallback(sText);
        }
    }

    _sendTextToClipboardFallback (sText) {
        try {
            // Copy to clipboard fallback
            // recipe from https://github.com/mdn/webextensions-examples/blob/master/context-menu-copy-link-with-types/clipboard-helper.js
            function setClipboardData (xEvent) {
                document.removeEventListener("copy", setClipboardData, true);
                xEvent.stopImmediatePropagation();
                xEvent.preventDefault();
                xEvent.clipboardData.setData("text/plain", sText);
            }
            document.addEventListener("copy", setClipboardData, true);
            document.execCommand("copy");
            window.setTimeout(() => { this.xClipboardButton.textContent = "📋"; }, 2000);
        }
        catch (e) {
            console.error(e);
        }
    }

    // Lexicographer