Grammalecte  Check-in [92e25df2da]

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

Overview
Comment:[fx] update: community dictionaries (draft)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fx | comdic
Files: files | file ages | folders
SHA3-256:92e25df2da16f8e8c6a1dda0a44acb1d18eaea31e8f2b0306d5a800a2564028c
User & Date: olr 2018-12-13 10:41:40
Context
2018-12-17
15:32
[fx] dictionaries selection (update) check-in: d784ee1493 user: olr tags: comdic, fx
2018-12-13
10:41
[fx] update: community dictionaries (draft) check-in: 92e25df2da user: olr tags: comdic, fx
2018-12-12
11:02
[fx] lexicon editor: ui rework -> save button always visible check-in: 46191a94a9 user: olr tags: comdic, fx
Changes

Changes to gc_lang/fr/webext/background.js.

   222    222               openConjugueurTab();
   223    223               break;
   224    224           case "openLexiconEditor":
   225    225               openLexiconEditor(dParam["dictionary"]);
   226    226               break;
   227    227           case "openDictionaries":
   228    228               openDictionaries();
          229  +            break;
   229    230           default:
   230    231               console.log("[background] Unknown command: " + sCommand);
   231    232               console.log(oRequest);
   232    233       }
   233    234       //sendResponse({response: "response from background script"});
   234    235   }
   235    236   
................................................................................
   285    286   browser.contextMenus.create({ id: "rightClickLxgEditableNode",  title: "Lexicographe (zone de texte)",              contexts: ["editable"] });
   286    287   browser.contextMenus.create({ id: "rightClickGCEditableNode",   title: "Correction grammaticale (zone de texte)",   contexts: ["editable"] });
   287    288   browser.contextMenus.create({ id: "separator_editable",         type: "separator",                                  contexts: ["editable"] });
   288    289   // Page
   289    290   browser.contextMenus.create({ id: "rightClickLxgPage",          title: "Lexicographe (page)",                       contexts: ["all"] }); // on all parts, due to unwanted selection
   290    291   browser.contextMenus.create({ id: "rightClickGCPage",           title: "Correction grammaticale (page)",            contexts: ["all"] });
   291    292   browser.contextMenus.create({ id: "separator_page",             type: "separator",                                  contexts: ["all"] });
   292         -// Conjugueur
          293  +// Tools
   293    294   browser.contextMenus.create({ id: "conjugueur_window",          title: "Conjugueur [fenêtre]",                      contexts: ["all"] });
   294    295   browser.contextMenus.create({ id: "conjugueur_tab",             title: "Conjugueur [onglet]",                       contexts: ["all"] });
          296  +browser.contextMenus.create({ id: "dictionaries",               title: "Dictionnaires",                             contexts: ["all"] });
          297  +browser.contextMenus.create({ id: "lexicon_editor",             title: "Éditeur lexical",                           contexts: ["all"] });
   295    298   // Rescan page
   296    299   browser.contextMenus.create({ id: "separator_rescan",           type: "separator",                                  contexts: ["editable"] });
   297    300   browser.contextMenus.create({ id: "rescanPage",                 title: "Rechercher à nouveau les zones de texte",   contexts: ["editable"] });
   298    301   
   299    302   
   300    303   browser.contextMenus.onClicked.addListener(function (xInfo, xTab) {
   301    304       // xInfo = https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/contextMenus/OnClickData
................................................................................
   331    334           // conjugueur
   332    335           case "conjugueur_window":
   333    336               openConjugueurWindow();
   334    337               break;
   335    338           case "conjugueur_tab":
   336    339               openConjugueurTab();
   337    340               break;
          341  +        case "lexicon_editor":
          342  +            openLexiconEditor();
          343  +            break;
          344  +        case "dictionaries":
          345  +            openDictionaries();
          346  +            break;
   338    347           // rescan page
   339    348           case "rescanPage":
   340    349               let xPort = dConnx.get(xTab.id);
   341    350               xPort.postMessage({sActionDone: "rescanPage"});
   342    351               break;
   343    352           default:
   344    353               console.log("[Background] Unknown menu id: " + xInfo.menuItemId);
................................................................................
   355    364       switch (sCommand) {
   356    365           case "conjugueur_tab":
   357    366               openConjugueurTab();
   358    367               break;
   359    368           case "conjugueur_window":
   360    369               openConjugueurWindow();
   361    370               break;
   362         -        case "lex_editor":
          371  +        case "lexicon_editor":
   363    372               openLexiconEditor();
   364    373               break;
          374  +        case "dictionaries":
          375  +            openDictionaries();
          376  +            break;
   365    377       }
   366    378   });
   367    379   
   368    380   
   369    381   /*
   370    382       Tabs
   371    383   */

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

    77     77         ],
    78     78         "run_at": "document_idle"
    79     79       }
    80     80     ],
    81     81   
    82     82     "commands": {
    83     83       "conjugueur_tab": {
    84         -      "suggested_key": {
    85         -        "default": "Ctrl+Shift+6"
    86         -      },
           84  +      "suggested_key": { "default": "Ctrl+Shift+6" },
    87     85         "description": "Ouvre le conjugueur dans un onglet"
    88     86       },
    89     87       "conjugueur_window": {
    90         -      "suggested_key": {
    91         -        "default": "Ctrl+Shift+7"
    92         -      },
           88  +      "suggested_key": { "default": "Ctrl+Shift+7" },
    93     89         "description": "Ouvre le conjugueur dans une fenêtre"
    94     90       },
    95         -    "lex_editor": {
    96         -      "suggested_key": {
    97         -        "default": "Ctrl+Shift+8"
    98         -      },
           91  +    "lexicon_editor": {
           92  +      "suggested_key": { "default": "Ctrl+Shift+8" },
    99     93         "description": "Ouvre l’éditeur lexical"
           94  +    },
           95  +    "dictionaries": {
           96  +      "suggested_key": { "default": "Ctrl+Shift+9" },
           97  +      "description": "Ouvre le gestionnaire de dictionnaires communautaires"
   100     98       }
   101     99     },
   102    100   
   103    101     "web_accessible_resources": [
   104    102       "content_scripts/panel.css",
   105    103       "content_scripts/panel_tf.css",
   106    104       "content_scripts/panel_gc.css",

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

     1      1   /*
     2         -    CSS
            2  +   CSS Document
            3  +   White
            4  +   Design par Olivier R.
            5  +*/
            6  +
            7  +* { margin: 0; padding: 0; }
            8  +img { border: none; }
            9  +
           10  +
           11  +/* Generic classes */
           12  +
           13  +.fleft { float: left; }
           14  +.fright { float: right; }
           15  +.center { text-align: center; }
           16  +.right { text-align: right; }
           17  +.left { text-align: left; }
           18  +.justify { text-align: justify; }
           19  +.hidden { display: none; }
           20  +.clearer { clear: both; font-size: 0; height: 0; }
           21  +
           22  +body {
           23  +    background: hsl(0, 0%, 100%) url(../img/lines.png);
           24  +    font: normal 16px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
           25  +    color: #505050;
           26  +}
           27  +
           28  +.inbox {
           29  +    width: 800px;
           30  +    margin: 20px auto 10px auto;
           31  +    padding: 10px 30px 30px 30px;
           32  +    background: hsl(0, 0%, 100%);
           33  +    border: 2px solid hsl(210, 0%, 90%);
           34  +    border-radius: 20px;
           35  +}
           36  +
           37  +h1 {
           38  +    margin: 5px 0 5px 0;
           39  +    color: hsl(210, 50%, 50%);
           40  +    font: bold 30px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
           41  +    text-align: center;
           42  +}
           43  +h2 {
           44  +    margin: 5px 0 2px 0;
           45  +    color: hsl(0, 50%, 50%);
           46  +    font: bold 20px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
           47  +}
           48  +h3 {
           49  +    margin: 3px 0 2px 0;
           50  +    color: hsl(210, 50%, 50%);
           51  +    font: bold 16px "Trebuchet MS", "Fira Sans", "Liberation Sans", sans-serif;
           52  +}
           53  +
           54  +
           55  +/*
           56  +    Main buttons
           57  +*/
           58  +
           59  +
           60  +.columns {
           61  +    display: flex;
           62  +}
           63  +
           64  +
           65  +ul {
           66  +    margin-left: 30px;
           67  +}
           68  +
           69  +input[type=text].large {
           70  +    display: inline-block;
           71  +    width: 250px;
           72  +    padding: 5px 10px;
           73  +    border: 2px solid hsl(0, 0%, 80%);
           74  +    border-radius: 3px;
           75  +    height: 24px;
           76  +    background: transparent;
           77  +    font: normal 20px Tahoma, "Ubuntu Condensed";
           78  +    color: hsl(0, 0%, 20%);
           79  +}
           80  +
           81  +input[type=text].medium {
           82  +    display: inline-block;
           83  +    width: 175px;
           84  +    padding: 2px 5px;
           85  +    border: 2px solid hsl(0, 0%, 80%);
           86  +    border-radius: 3px;
           87  +    height: 20px;
           88  +    background: transparent;
           89  +    font: normal 18px Tahoma, "Ubuntu Condensed";
           90  +    color: hsl(0, 0%, 20%);
           91  +}
           92  +
           93  +input[placeholder] {
           94  +    color: hsl(0, 0%, 50%);
           95  +}
           96  +
           97  +
           98  +
           99  +/*
          100  +    Table
     3    101   */
          102  +#wait_progress {
          103  +    width: 100%;
          104  +    height: 4px;
          105  +}
          106  +
          107  +table {
          108  +    border: 1px solid hsl(210, 10%, 50%);
          109  +    width: 100%;
          110  +}
          111  +th {
          112  +    padding: 5px 10px;
          113  +    border-left: 1px solid hsl(210, 10%, 90%);
          114  +    text-align: left;
          115  +}
          116  +td {
          117  +    padding: 0 10px;
          118  +    vertical-align: top;
          119  +}
          120  +.delete_entry {
          121  +    cursor: pointer;
          122  +    font-weight: bold;
          123  +    color: hsl(0, 100%, 50%);
          124  +}
          125  +.select_entry {
          126  +    cursor: pointer;
          127  +    background-color: hsl(120, 50%, 30%);
          128  +    color: hsl(120, 50%, 100%);
          129  +    border-radius: 3px;
          130  +    text-align: center;
          131  +}

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

     8      8   
     9      9     <body>
    10     10   
    11     11       <div class="inbox">
    12     12   
    13     13         <h1>Dictionnaires communautaires</h1>
    14     14   
    15         -      <div id="lexicon_page">
    16         -        <h2>Votre lexique</h2>
    17         -        <div class="big_block">
    18         -          <div id="save_button" class="fright">
    19         -            Enregistrer
    20         -          </div>
    21         -          <p>Nombre d’entrées : <span id="num_entries">0</span>.</p>
    22         -        </div>
           15  +        <h2>Dictionnaires sélectionnés</h2>
           16  +        <p id="dictionaries_list">[Aucun]<p>
    23     17   
    24         -        <table id="lexicon_table">
    25         -
           18  +        <h2>Dictionnaires disponibles sur le serveur de Grammalecte</h2>
           19  +        <progress id="wait_progress" value="0"></progress>
           20  +        <table id="dictionaries_table">
    26     21           </table>
    27         -      </div> <!-- #lexicon_page -->
    28         -
    29     22   
    30     23       </div>
    31     24   
    32     25   
    33     26       <script src="../grammalecte/graphspell/helpers.js"></script>
    34     27       <script src="../grammalecte/graphspell/char_player.js"></script>
    35     28       <script src="../grammalecte/graphspell/str_transform.js"></script>
    36         -    <script src="../grammalecte/graphspell/dawg.js"></script>
    37     29       <script src="../grammalecte/graphspell/ibdawg.js"></script>
    38     30       <script src="../grammalecte/graphspell/spellchecker.js"></script>
    39         -    <script src="../grammalecte/fr/conj.js"></script>
    40         -    <script src="../grammalecte/fr/conj_generator.js"></script>
    41         -    <script src="../grammalecte/fr/lexicographe.js"></script>
    42     31       <script src="dictionaries.js"></script>
    43     32     </body>
    44     33   
    45     34   </html>

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

     1      1   // JavaScript
     2      2   
     3      3   "use strict";
     4      4   
            5  +
            6  +// Chrome don’t follow the W3C specification:
            7  +// https://browserext.github.io/browserext/
            8  +let bChrome = false;
            9  +if (typeof(browser) !== "object") {
           10  +    var browser = chrome;
           11  +    bChrome = true;
           12  +}
           13  +
           14  +
           15  +/*
           16  +    Common functions
           17  +*/
           18  +
           19  +function showError (e) {
           20  +    console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
           21  +}
           22  +
           23  +function createNode  (sType, oAttr, oDataset=null) {
           24  +    try {
           25  +        let xNode = document.createElement(sType);
           26  +        Object.assign(xNode, oAttr);
           27  +        if (oDataset) {
           28  +            Object.assign(xNode.dataset, oDataset);
           29  +        }
           30  +        return xNode;
           31  +    }
           32  +    catch (e) {
           33  +        showError(e);
           34  +    }
           35  +}
           36  +
           37  +
           38  +
           39  +class Table {
           40  +
           41  +    constructor (sNodeId, lColumn, sProgressBarId, sResultId="", bDeleteButtons=true, bActionButtons) {
           42  +        this.sNodeId = sNodeId;
           43  +        this.xTable = document.getElementById(sNodeId);
           44  +        this.nColumn = lColumn.length;
           45  +        this.lColumn = lColumn;
           46  +        this.xProgressBar = document.getElementById(sProgressBarId);
           47  +        this.xNumEntry = document.getElementById(sResultId);
           48  +        this.iEntryIndex = 0;
           49  +        this.lEntry = [];
           50  +        this.nEntry = 0;
           51  +        this.bDeleteButtons = bDeleteButtons;
           52  +        this.bActionButtons = bActionButtons;
           53  +        this._createHeader();
           54  +        this.listen();
           55  +    }
           56  +
           57  +    _createHeader () {
           58  +        let xRowNode = createNode("tr");
           59  +        if (this.bDeleteButtons) {
           60  +            xRowNode.appendChild(createNode("th", { textContent: "·", width: "12px" }));
           61  +        }
           62  +        for (let sColumn of this.lColumn) {
           63  +            xRowNode.appendChild(createNode("th", { textContent: sColumn }));
           64  +        }
           65  +        this.xTable.appendChild(xRowNode);
           66  +    }
           67  +
           68  +    clear () {
           69  +        while (this.xTable.firstChild) {
           70  +            this.xTable.removeChild(this.xTable.firstChild);
           71  +        }
           72  +        this.lEntry = [];
           73  +        this.nEntry = 0;
           74  +        this.iEntryIndex = 0;
           75  +        this._createHeader();
           76  +        this.showEntryNumber();
           77  +    }
           78  +
           79  +    fill (lFlex) {
           80  +        this.clear();
           81  +        if (lFlex.length > 0) {
           82  +            this.xProgressBar.max = lFlex.length;
           83  +            this.xProgressBar.value = 1;
           84  +            for (let lData of lFlex) {
           85  +                this._addRow(lData);
           86  +                this.xProgressBar.value += 1;
           87  +            }
           88  +            this.xProgressBar.value = this.xProgressBar.max;
           89  +        }
           90  +        this.lEntry = lFlex;
           91  +        this.nEntry = lFlex.length;
           92  +        this.showEntryNumber();
           93  +    }
           94  +
           95  +    addEntries (lFlex) {
           96  +        this.lEntry.push(...lFlex);
           97  +        for (let lData of lFlex) {
           98  +            this._addRow(lData);
           99  +        }
          100  +        this.nEntry += lFlex.length;
          101  +        this.showEntryNumber();
          102  +    }
          103  +
          104  +    showEntryNumber () {
          105  +        if (this.xNumEntry) {
          106  +            this.xNumEntry.textContent = this.nEntry;
          107  +        }
          108  +    }
          109  +
          110  +    _addRow (lData) {
          111  +        let xRowNode = createNode("tr", { id: this.sNodeId + "_row_" + this.iEntryIndex });
          112  +        if (this.bDeleteButtons) {
          113  +            xRowNode.appendChild(createNode("td", { textContent: "×", className: "delete_entry", title: "Effacer cette entrée" }, { id_entry: this.iEntryIndex }));
          114  +        }
          115  +        for (let data of lData) {
          116  +            xRowNode.appendChild(createNode("td", { textContent: data }));
          117  +        }
          118  +        if (this.bActionButtons) {
          119  +            xRowNode.appendChild(createNode("td", { textContent: "+", className: "select_entry", title: "Sélectionner/Désélectionner cette entrée" }, { id_entry: this.iEntryIndex }));
          120  +        }
          121  +        this.xTable.appendChild(xRowNode);
          122  +        this.iEntryIndex += 1;
          123  +    }
          124  +
          125  +    listen () {
          126  +        if (this.bDeleteButtons || this.bActionButtons) {
          127  +            this.xTable.addEventListener("click", (xEvent) => { this.onTableClick(xEvent); }, false);
          128  +        }
          129  +    }
          130  +
          131  +    onTableClick (xEvent) {
          132  +        try {
          133  +            let xElem = xEvent.target;
          134  +            if (xElem.className) {
          135  +                switch (xElem.className) {
          136  +                    case "delete_entry": this.deleteRow(xElem.dataset.id_entry); break;
          137  +                    case "select_entry": this.selectEntry(xElem.dataset.id_entry); break;
          138  +                }
          139  +            }
          140  +        }
          141  +        catch (e) {
          142  +            showError(e);
          143  +        }
          144  +    }
          145  +
          146  +    deleteRow (iEntry) {
          147  +        this.lEntry[parseInt(iEntry)] = null;
          148  +        if (document.getElementById(this.sNodeId + "_row_" + iEntry)) {
          149  +            document.getElementById(this.sNodeId + "_row_" + iEntry).style.display = "none";
          150  +        }
          151  +        this.nEntry -= 1;
          152  +        this.showEntryNumber();
          153  +        if (this.sNodeId == "lexicon_table") {
          154  +            showElement("save_button", "inline-block");
          155  +        }
          156  +    }
          157  +
          158  +    selectEntry (iEntry) {
          159  +        let sRowId = this.sNodeId + "_row_" + iEntry;
          160  +        document.getElementById(sRowId).style.backgroundColor = "hsl(120, 50%, 90%)";
          161  +    }
          162  +
          163  +    getEntries () {
          164  +        return this.lEntry.filter((e) => e !== null);
          165  +    }
          166  +}
          167  +
          168  +
          169  +const oDicTable = new Table("dictionaries_table", ["Nom", "Créé par", "Entrées", "Description"], "wait_progress", "", false, true);
          170  +
          171  +oDicTable.fill([
          172  +    ["Ambre", "Inconnu", "240", "Univers des Princes d’Ambre (de Roger Zelazny)"],
          173  +    ["Malaz", "Inconnu", "2340", "Univers du Livre des Martyrs (de Steven Erikson)"],
          174  +    ["Pudlard", "Inconnu", "1440", "Univers d’Harry Potter de XXXX"],
          175  +    ["Dune", "Inconnu", "2359", "Univers de Dune (de Frank Herbert)"],
          176  +    ["StarWars", "Inconnu", "4359", "Univers de Star Wars (de George Lucas)"]
          177  +]);

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

   552    552           this.sName = sName;
   553    553           let oJSON = oDictHandler.getDictionary(sName);
   554    554           if (oJSON) {
   555    555               this.parseDict(oJSON);
   556    556           } else {
   557    557               oLexiconTable.clear();
   558    558               this.setDictData(0, "[néant]");
          559  +            hideElement("save_button");
   559    560           }
   560    561       },
   561    562   
   562    563       parseDict: function (oJSON) {
   563    564           try {
   564    565               this.oIBDAWG = new IBDAWG(oJSON);
   565    566           }
................................................................................
   570    571           }
   571    572           let lEntry = [];
   572    573           for (let aRes of this.oIBDAWG.select()) {
   573    574               lEntry.push(aRes);
   574    575           }
   575    576           oLexiconTable.fill(lEntry);
   576    577           this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
          578  +        hideElement("save_button");
   577    579       },
   578    580   
   579    581       import: function () {
   580    582           let xInput = document.getElementById("import_input");
   581    583           let xFile = xInput.files[0];
   582    584           let xURL = URL.createObjectURL(xFile);
   583    585           let sJSON = helpers.loadFile(xURL);

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

    90     90             <h2>Raccourcis clavier</h2>
    91     91             <p class="shortcut">CTRL+MAJ+6</p>
    92     92             <p class="shortcut_label">Conjugueur (dans un onglet)</p>
    93     93             <p class="shortcut">CTRL+MAJ+7</p>
    94     94             <p class="shortcut_label">Conjugueur (dans une fenêtre)</p>
    95     95             <p class="shortcut">CTRL+MAJ+8</p>
    96     96             <p class="shortcut_label">Éditeur lexical</p>
           97  +          <p class="shortcut">CTRL+MAJ+9</p>
           98  +          <p class="shortcut_label">Dictionnaires communautaires</p>
    97     99           </section> <!-- #ui_options_page -->
    98    100   
    99    101           <section id="gc_options_page" class="page">
   100    102             <h1>OPTIONS GRAMMATICALES</h1>
   101    103             <div id="grammar_options">
   102    104               ${webextOptionsHTML}
   103    105             </div>
................................................................................
   112    114                   <p><input type="checkbox" id="main_dic" data-dictionary="main" checked disabled="disabled" /> <label for="main_dic">Dictionnaire principal</label></p>
   113    115                   <p class="option_description">Environ 83 000 entrées, 500 000 flexions.<br/>Ni éditable, ni désactivable.<br/>Ce dictionnaire est créé à partir du dictionnaire orthographique pour Firefox et LibreOffice, conçu sur le <a id="link_grammalecte" class="link" data-url="http://grammalecte.net/home.php?prj=fr">site de Grammalecte</a>.</p>
   114    116               </div>
   115    117               <div class="option_section" id="community_dic_box">
   116    118                   <p><input type="checkbox" id="community_dic" data-dictionary="community" /> <label for="community_dic">Dictionnaire communautaire</label></p>
   117    119                   <p class="option_description">Ce dictionnaire est créé et édité via l’éditeur lexical et est sauvegardé sur un serveur en ligne accessible à tous les membres.</p>
   118    120                   <div class="button_row">
   119         -                  <div class="dic_button" id="dictionaries_button">Dictionnaires en ligne</div>
   120    121                     <div class="dic_button" id="dic_community_button">Éditer</div>
          122  +                  <div class="dic_button" id="dictionaries_button">Dictionnaires en ligne</div>
   121    123                   </div>
   122    124               </div>
   123    125               <div class="option_section" id="personal_dic_box">
   124    126                   <p><input type="checkbox" id="personal_dic" data-dictionary="personal" /> <label for="personal_dic">Dictionnaire personnel</label></p>
   125    127                   <p class="option_description">Ce dictionnaire est créé et édité via l’éditeur lexical et n’est pas partagé.</p>
   126    128                   <div class="button_row">
   127    129                     <div class="dic_button" id="dic_personal_button">Éditer</div>