// JavaScript
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch("extensions.grammarchecker.");
/*
Common functions
*/
function showError (e) {
Cu.reportError(e);
console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
}
function createNode (sType, oAttr) {
try {
let xNode = document.createElement(sType);
for (let sParam in oAttr) {
xNode.setAttribute(sParam, oAttr[sParam]);
}
return xNode;
}
catch (e) {
showError(e);
}
}
function enableElement (sElemId) {
if (document.getElementById(sElemId)) {
document.getElementById(sElemId).disabled = false;
} else {
console.log("HTML node named <" + sElemId + "> not found.")
}
}
function disableElement (sElemId) {
if (document.getElementById(sElemId)) {
document.getElementById(sElemId).disabled = true;
} else {
console.log("HTML node named <" + sElemId + "> not found.")
}
}
class Table {
constructor (sNodeId, lColumn, lColumnWidth, sProgressBarId, sResultId="") {
this.sNodeId = sNodeId;
this.xTable = document.getElementById(sNodeId);
this.nColumn = lColumn.length;
this.lColumn = lColumn;
this.lColumnWidth = lColumnWidth;
this.xProgressBar = document.getElementById(sProgressBarId);
this.xNumEntry = document.getElementById(sResultId);
this.iEntryIndex = 0;
this.lEntry = [];
this.nEntry = 0
this._createHeader();
this.listen();
}
_createHeader () {
let xListheadNode = createNode("listhead");
xListheadNode.appendChild(createNode("listheader", { label: "·", width: "12px" }));
for (let sColumn of this.lColumn) {
xListheadNode.appendChild(createNode("listheader", { label: sColumn }));
}
this.xTable.appendChild(xListheadNode);
let xListcolsNode = createNode("listcols");
xListcolsNode.appendChild(createNode("listcol", { flex: 1 }));
for (let cColumn of this.lColumnWidth) {
xListcolsNode.appendChild(createNode("listcol", { flex: cColumn }));
}
this.xTable.appendChild(xListcolsNode);
}
clear () {
while (this.xTable.firstChild) {
this.xTable.removeChild(this.xTable.firstChild);
}
this.iEntryIndex = 0;
this._createHeader();
}
fill (lFlex) {
this.clear();
if (lFlex.length > 0) {
this.xProgressBar.max = lFlex.length;
this.xProgressBar.value = 1;
for (let lData of lFlex) {
this._addRow(lData);
this.xProgressBar.value += 1;
}
this.xProgressBar.value = this.xProgressBar.max;
}
this.lEntry = lFlex;
this.nEntry = lFlex.length;
this.showEntryNumber();
}
addEntries (lFlex) {
this.lEntry.push(...lFlex);
for (let lData of lFlex) {
this._addRow(lData);
}
this.nEntry += lFlex.length;
this.showEntryNumber();
}
showEntryNumber () {
if (this.xNumEntry) {
this.xNumEntry.textContent = this.nEntry;
}
}
_addRow (lData) {
let xRowNode = createNode("listitem", { id: this.sNodeId + "_row_" + this.iEntryIndex });
xRowNode.appendChild(createNode("listcell", { label: "×", className: "delete_entry", title: "Effacer cette entrée", value: this.iEntryIndex }));
//xRowNode.appendChild(createNode("listcell", { label: this.iEntryIndex }));
for (let data of lData) {
xRowNode.appendChild(createNode("listcell", { label: data }));
}
this.xTable.appendChild(xRowNode);
this.iEntryIndex += 1;
}
listen () {
this.xTable.addEventListener("click", (xEvent) => { this.onTableClick(xEvent); }, false);
}
onTableClick (xEvent) {
try {
let xElem = xEvent.target;
if (xElem.className) {
if (xElem.className == "delete_entry") {
this.deleteRow(xElem.value);
}
}
}
catch (e) {
showError(e);
}
}
deleteRow (iEntry) {
this.lEntry[parseInt(iEntry)] = null;
if (document.getElementById(this.sNodeId + "_row_" + iEntry)) {
document.getElementById(this.sNodeId + "_row_" + iEntry).style.display = "none";
}
this.nEntry -= 1;
this.showEntryNumber();
}
getEntries () {
return this.lEntry.filter((e) => e !== null);
}
}
const oGenerator = {
sLemma: "",
cMainTag: "",
lFlexion: [],
listen: function () {
document.getElementById("lemma").addEventListener("keyup", () => { this.update(); }, false);
// nom commun
document.getElementById("tag_N").addEventListener("click", () => { this.update("N"); }, false);
document.getElementById("nom_adj").addEventListener("click", () => { this.update(); }, false);
document.getElementById("nom").addEventListener("click", () => { this.update(); }, false);
document.getElementById("adj").addEventListener("click", () => { this.update(); }, false);
document.getElementById("N_epi").addEventListener("click", () => { this.update(); }, false);
document.getElementById("N_mas").addEventListener("click", () => { this.update(); }, false);
document.getElementById("N_fem").addEventListener("click", () => { this.update(); }, false);
document.getElementById("N_s").addEventListener("click", () => { this.update(); }, false);
document.getElementById("N_x").addEventListener("click", () => { this.update(); }, false);
document.getElementById("N_inv").addEventListener("click", () => { this.update(); }, false);
document.getElementById("lemma2").addEventListener("keyup", () => { this.update(); }, false);
// nom propre
document.getElementById("tag_M").addEventListener("click", () => { this.update("M"); }, false);
document.getElementById("M1").addEventListener("click", () => { this.update(); }, false);
document.getElementById("M2").addEventListener("click", () => { this.update(); }, false);
document.getElementById("MP").addEventListener("click", () => { this.update(); }, false);
document.getElementById("M_epi").addEventListener("click", () => { this.update(); }, false);
document.getElementById("M_mas").addEventListener("click", () => { this.update(); }, false);
document.getElementById("M_fem").addEventListener("click", () => { this.update(); }, false);
// verbe
document.getElementById("tag_V").addEventListener("click", () => { this.update("V"); }, false);
document.getElementById("v_i").addEventListener("click", () => { this.update(); }, false);
document.getElementById("v_t").addEventListener("click", () => { this.update(); }, false);
document.getElementById("v_n").addEventListener("click", () => { this.update(); }, false);
document.getElementById("v_p").addEventListener("click", () => { this.update(); }, false);
document.getElementById("v_m").addEventListener("click", () => { this.update(); }, false);
document.getElementById("v_ae").addEventListener("click", () => { this.update(); }, false);
document.getElementById("v_aa").addEventListener("click", () => { this.update(); }, false);
document.getElementById("v_ppas").addEventListener("click", () => { this.update(); }, false);
document.getElementById("verbe_modele").addEventListener("keyup", () => { this.update(); }, false);
// adverbe
document.getElementById("tag_W").addEventListener("click", () => { this.update("W"); }, false);
// autre
document.getElementById("tag_X").addEventListener("click", () => { this.update("X"); }, false);
document.getElementById("flexion").addEventListener("keyup", () => { this.update(); }, false);
document.getElementById("tags").addEventListener("keyup", () => { this.update(); }, false);
// ajout
document.getElementById("add_to_lexicon").addEventListener("click", () => { this.addToLexicon(); }, false);
},
clear: function () {
try {
// nom commun
document.getElementById("tag_N").checked = false;
document.getElementById("nom_adj").checked = false;
document.getElementById("nom").checked = false;
document.getElementById("adj").checked = false;
document.getElementById("N_epi").checked = false;
document.getElementById("N_mas").checked = false;
document.getElementById("N_fem").checked = false;
document.getElementById("N_s").checked = false;
document.getElementById("N_x").checked = false;
document.getElementById("N_inv").checked = false;
document.getElementById("lemma2").value = "";
// nom propre
document.getElementById("tag_M").checked = false;
document.getElementById("M1").checked = false;
document.getElementById("M2").checked = false;
document.getElementById("MP").checked = false;
document.getElementById("M_epi").checked = false;
document.getElementById("M_mas").checked = false;
document.getElementById("M_fem").checked = false;
// verbe
document.getElementById("tag_V").checked = false;
document.getElementById("v_i").checked = false;
document.getElementById("v_t").checked = false;
document.getElementById("v_n").checked = false;
document.getElementById("v_p").checked = false;
document.getElementById("v_m").checked = false;
document.getElementById("v_ae").checked = false;
document.getElementById("v_aa").checked = false;
document.getElementById("v_ppas").checked = true;
document.getElementById("verbe_modele").value = "";
// adverbe
document.getElementById("tag_W").checked = false;
// autre
document.getElementById("tag_X").checked = false;
document.getElementById("flexion").value = "";
document.getElementById("tags").value = "";
}
catch (e) {
showError(e);
}
},
lTag: ["N", "M", "V", "W", "X"],
setMainTag: function (cTag) {
this.cMainTag = cTag;
for (let c of this.lTag) {
if (c !== cTag) {
document.getElementById("tag_"+c).checked = false;
}
}
},
update: function (cTag=null) {
if (cTag !== null) {
this.setMainTag(cTag);
}
try {
this.lFlexion = [];
this.sLemma = document.getElementById("lemma").value.trim();
if (this.sLemma.length > 0) {
switch (this.cMainTag) {
case "N":
if (!this.getRadioValue("pos_nom_commun") || !this.getRadioValue("genre_nom_commun")) {
break;
}
let sTag = this.getRadioValue("pos_nom_commun") + this.getRadioValue("genre_nom_commun");
switch (this.getRadioValue("pluriel_nom_commun")) {
case "s":
this.lFlexion.push([this.sLemma, sTag+":s/*"]);
this.lFlexion.push([this.sLemma+"s", sTag+":p/*"]);
break;
case "x":
this.lFlexion.push([this.sLemma, sTag+":s/*"]);
this.lFlexion.push([this.sLemma+"x", sTag+":p/*"]);
break;
case "i":
this.lFlexion.push([this.sLemma, sTag+":i/*"]);
break;
}
let sLemma2 = document.getElementById("lemma2").value.trim();
if (sLemma2.length > 0 && this.getRadioValue("pos_nom_commun2") && this.getRadioValue("genre_nom_commun2")) {
let sTag2 = this.getRadioValue("pos_nom_commun2") + this.getRadioValue("genre_nom_commun2");
switch (this.getRadioValue("pluriel_nom_commun2")) {
case "s":
this.lFlexion.push([sLemma2, sTag2+":s/*"]);
this.lFlexion.push([sLemma2+"s", sTag2+":p/*"]);
break;
case "x":
this.lFlexion.push([sLemma2, sTag2+":s/*"]);
this.lFlexion.push([sLemma2+"x", sTag2+":p/*"]);
break;
case "i":
this.lFlexion.push([sLemma2, sTag2+":i/*"]);
break;
}
}
break;
case "V": {
if (!this.sLemma.endsWith("er") && !this.sLemma.endsWith("ir") && !this.sLemma.endsWith("re")) {
break;
}
this.sLemma = this.sLemma.toLowerCase();
let cGroup = "";
let c_i = (document.getElementById("v_i").checked) ? "i" : "_";
let c_t = (document.getElementById("v_t").checked) ? "t" : "_";
let c_n = (document.getElementById("v_n").checked) ? "n" : "_";
let c_p = (document.getElementById("v_p").checked) ? "p" : "_";
let c_m = (document.getElementById("v_m").checked) ? "m" : "_";
let c_ae = (document.getElementById("v_ae").checked) ? "e" : "_";
let c_aa = (document.getElementById("v_aa").checked) ? "a" : "_";
let sVerbTag = c_i + c_t + c_n + c_p + c_m + c_ae + c_aa;
if (!sVerbTag.endsWith("__") && !sVerbTag.startsWith("____")) {
let sVerbPattern = document.getElementById("verbe_modele").value.trim();
if (sVerbPattern.length == 0) {
// utilisation du générateur de conjugaison
let bVarPpas = document.getElementById("v_ppas").checked;
for (let [sFlexion, sFlexTags] of conj_generator.conjugate(this.sLemma, sVerbTag, bVarPpas)) {
this.lFlexion.push([sFlexion, sFlexTags]);
}
} else {
// copie du motif d’un autre verbe : utilisation du conjugueur
console.log("pattern: " + sVerbPattern);
if (conj.isVerb(sVerbPattern)) {
console.log("yes");
let oVerb = new Verb(this.sLemma, sVerbPattern);
for (let [sTag1, dFlex] of oVerb.dConj.entries()) {
if (sTag1 !== ":Q") {
for (let [sTag2, sConj] of dFlex.entries()) {
if (sTag2.startsWith(":") && sConj !== "") {
this.lFlexion.push([sConj, ":V" + oVerb.cGroup + "_" + sVerbTag + sTag1 + sTag2]);
}
}
} else {
// participes passés
if (dFlex.get(":Q3") !== "") {
if (dFlex.get(":Q2") !== "") {
this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:s/*"]);
this.lFlexion.push([dFlex.get(":Q2"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:p/*"]);
} else {
this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:m:i/*"]);
}
this.lFlexion.push([dFlex.get(":Q3"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:s/*"]);
this.lFlexion.push([dFlex.get(":Q4"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:A:f:p/*"]);
} else {
this.lFlexion.push([dFlex.get(":Q1"), ":V" + oVerb.cGroup + "_" + sVerbTag + ":Q:e:i/*"]);
}
}
}
}
}
}
break;
}
case "W":
this.sLemma = this.sLemma.toLowerCase();
this.lFlexion.push([this.sLemma, ":W/*"]);
break;
case "M":
this.sLemma = this.sLemma.slice(0,1).toUpperCase() + this.sLemma.slice(1);
let sPOSTag = this.getRadioValue("pos_nom_propre");
let sGenderTag = this.getRadioValue("genre_nom_propre");
if (sGenderTag) {
this.lFlexion.push([this.sLemma, sPOSTag+sGenderTag+":i/*"]);
}
break;
case "X":
let sFlexion = document.getElementById("flexion").value.trim();
let sTags = document.getElementById("tags").value.trim();
if (sFlexion.length > 0 && sTags.startsWith(":")) {
this.lFlexion.push([sFlexion, sTags]);
}
break;
}
}
oGenWordsTable.fill(this.lFlexion);
}
catch (e) {
showError(e);
}
},
getRadioValue: function (sName) {
if (document.getElementById(sName)) {
for (let xNode of document.getElementById(sName).children) {
if (xNode.selected) {
return xNode.value;
}
}
}
return null;
},
createFlexLemmaTagArray: function () {
let lEntry = [];
for (let [sFlex, sTags] of oGenWordsTable.getEntries()) {
lEntry.push([sFlex, this.sLemma, sTags]);
}
return lEntry;
},
addToLexicon: function () {
try {
oLexiconTable.addEntries(this.createFlexLemmaTagArray());
oGenWordsTable.clear();
document.getElementById("lemma").value = "";
document.getElementById("lemma").focus();
enableElement("save_button");
this.clear();
this.cMainTag = "";
}
catch (e) {
showError(e);
}
}
}
const oBinaryDict = {
oIBDAWG: null,
load: function () {
let sJSON = prefs.getCharPref("oPersonalDictionary");
if (sJSON != "") {
let oJSON = JSON.parse(sJSON);
this.oIBDAWG = new IBDAWG(oJSON);
let lEntry = [];
for (let s of this.oIBDAWG.select()) {
lEntry.push(s.split("\t"));
}
oLexiconTable.fill(lEntry);
this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
enableElement("export_button");
}
},
setDictData: function (nEntries, sDate) {
document.getElementById("dic_num_entries").value = nEntries;
document.getElementById("dic_save_date").value = sDate;
},
listen: function () {
document.getElementById("save_button").addEventListener("click", () => { this.build(); }, false);
document.getElementById("export_button").addEventListener("click", () => { this.export(); }, false);
//document.getElementById("import_button").addEventListener("click", () => { this.import(); }, false);
},
build: function () {
let xProgressNode = document.getElementById("wait_progress");
let lEntry = oLexiconTable.getEntries();
if (lEntry.length > 0) {
let oDAWG = new DAWG(lEntry, "S", "fr", "Français", "Dictionnaire personnel", xProgressNode);
let oJSON = oDAWG.createBinaryJSON(1);
prefs.setCharPref("oPersonalDictionary", JSON.stringify(oJSON));
this.oIBDAWG = new IBDAWG(oJSON);
this.setDictData(this.oIBDAWG.nEntry, this.oIBDAWG.sDate);
//browser.runtime.sendMessage({ sCommand: "setDictionary", dParam: {sType: "personal", oDict: oJSON}, dInfo: {} });
}
enableElement("export_button");
},
import: function () {
console.log("import");
},
export: function () {
let sJSON = JSON.stringify(this.oIBDAWG.getJSON());
let xFilePicker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
xFilePicker.init(window, "Enregistrer sous", Ci.nsIFilePicker.modeSave);
xFilePicker.appendFilters(Ci.nsIFilePicker.filterAll | Ci.nsIFilePicker.filterText);
xFilePicker.open(function (nReturnValue) {
if (nReturnValue == Ci.nsIFilePicker.returnOK || nReturnValue == Ci.nsIFilePicker.returnReplace) {
// https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/OSFile.jsm
OS.File.writeAtomic(xFilePicker.file.path, sJSON, {tmpPath: "file.txt.tmp"});
/*
var FileUtils = Cu.import("resource://gre/modules/FileUtils.jsm").FileUtils
var NetUtil = Cu.import("resource://gre/modules/NetUtil.jsm").NetUtil;
// You can also optionally pass a flags parameter here. It defaults to
// FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE;
let xOutStream = FileUtils.openSafeFileOutputStream(xFilePicker.file);
let xConverter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
xConverter.charset = "UTF-8";
let xInStream = xConverter.convertToInputStream(sJSON);
// The last argument (the callback) is optional.
NetUtil.asyncCopy(xInStream, xOutStream, function (status) {
if (!Components.isSuccessCode(status)) {
console.log(status);
return;
}
});
*/
}
});
}
}
const oLexiconTable = new Table("lexicon_table", ["Flexions", "Lemmes", "Étiquettes"], [10, 7, 10],"progress_lexicon", "num_entries");
const oGenWordsTable = new Table("generated_words_table", ["Flexions", "Étiquettes"], [10, 10], "progress_new_words");
oBinaryDict.load();
oBinaryDict.listen();
oGenerator.listen();