Ajout de la fonctionnalité Favoris (V2.2)

- Nouvelle catégorie Favoris: recuperation des favoris depuis Project.gfx (getFavorites.dg5)
- Pages menuFavorites.dg5 et showDataFav.dg5 + bibliothèques JSZip/jQuery
- Navigation index.dg5: ajout de la catégorie Favoris
- Correctif override.dg5: exclusion des points /services/subnet
- Bump version 2.2 et description "Alternative to Command"
- Mise a jour README (doc Favoris + changelog)
This commit is contained in:
2026-06-10 05:54:31 +02:00
parent fbd191d9dc
commit c6482c396d
13 changed files with 279 additions and 9 deletions
+154
View File
@@ -0,0 +1,154 @@
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript' src='jquery-3.7.1.min.js'></script>
<script type='text/javascript' src='jszip.min.js'></script>
<script type='text/javascript' src='jszip-utils.min.js'></script>
<script type='text/javascript' src='dgframe.js'></script>
</head>
<body>
<div id="fetch"></div>
<script type='text/javascript'>
"use strict";
let zipSource = "";
let fileContent;
let blacklistFiles = "";
let blacklistSet = new Set();
let dgParams = {
"zipSource": function(val) {
zipSource = val;
unzip(zipSource);
},
"blacklistFiles": function(val) {
blacklistFiles = val;
blacklistSet = parseBlacklist(val);
},
"fileContent": function(val) {
fileContent = val;
}
};
// "chemin1,chemin2,..." -> Set de chemins normalises (slashes en /)
function parseBlacklist(str) {
let set = new Set();
if (!str) {
return set;
}
str.split(",").forEach(function(p) {
let norm = p.trim().replace(/\\/g, "/");
if (norm) {
set.add(norm);
}
});
return set;
}
// Prepare la donnee a charger par JSZip selon la forme recue.
// JSZip.loadAsync accepte aussi bien une chaine binaire qu'un Uint8Array.
function toZipData(input) {
if (typeof input === "string") {
let trimmed = input.trim();
// Reponse JSON {"binary":"<base64>"} -> decoder le base64
if (trimmed.charAt(0) === "{") {
let base64 = JSON.parse(trimmed).binary;
let bin = atob(base64);
let out = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) {
out[i] = bin.charCodeAt(i);
}
return out;
}
// Tableau d'octets en texte "[123,34,...]"
if (trimmed.charAt(0) === "[") {
return Uint8Array.from(JSON.parse(trimmed));
}
// Zip brut en chaine binaire (commence par "PK") -> JSZip l'accepte tel quel
return input;
}
// ArrayBuffer / TypedArray / tableau d'octets -> JSZip l'accepte tel quel
return input;
}
// Octets -> base64 (navigateur)
function bytesToBase64(bytes) {
let bin = "";
for (let i = 0; i < bytes.length; i++) {
bin += String.fromCharCode(bytes[i]);
}
return btoa(bin);
}
// Type MIME a partir de l'extension du fichier
function mimeFromName(name) {
let ext = name.split(".").pop().toLowerCase();
let map = {
png: "image/png", jpg: "image/jpeg", jpeg: "image/jpeg",
gif: "image/gif", bmp: "image/bmp", webp: "image/webp",
ico: "image/x-icon", svg: "image/svg+xml"
};
return map[ext] || "application/octet-stream";
}
// Decode le contenu d'un fichier selon son encodage reel.
// Texte: UTF-16 (BOM) ou UTF-8. Binaire (image): data URI base64 pour <img src="">.
function decodeContent(bytes, name) {
if (bytes.length >= 2 && bytes[0] === 0xFF && bytes[1] === 0xFE) {
return new TextDecoder("utf-16le").decode(bytes);
}
if (bytes.length >= 2 && bytes[0] === 0xFE && bytes[1] === 0xFF) {
return new TextDecoder("utf-16be").decode(bytes);
}
try {
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
} catch (e) {
return "data:" + mimeFromName(name) + ";base64," + bytesToBase64(bytes);
}
}
function unzip(source) {
let zipData;
try {
zipData = toZipData(source);
} catch (e) {
console.log("Erreur de decodage de l'entree:", e);
return;
}
JSZip.loadAsync(zipData)
.then(function(zip) {
let promises = [];
zip.forEach(function (relativePath, zipEntry) {
if (zipEntry.dir) {
return;
}
// Exclu: ni dans la table, ni chargement du contenu (memoire)
if (blacklistSet.has(relativePath.replace(/\\/g, "/"))) {
return;
}
promises.push(
zipEntry.async("uint8array").then(function(bytes) {
return {
name: zipEntry.name.split("/").pop().split("\\").pop(),
path: relativePath,
content: decodeContent(bytes, zipEntry.name)
};
})
);
});
return Promise.all(promises);
})
.then(function success(table) {
dgUpdateParams({ 'fileContent': JSON.stringify(table, null, 2) });
}, function error(e) {
console.log("Erreur de lecture du zip:", e);
});
}
</script>
</body>
</html>