Annuaire › Code ouvert
Code publié par son auteur, en lecture seule. « Copier dans mon espace » crée un nouveau site à vous (non publié) que vous pouvez modifier librement.
js/outils.js · 4.5 Ko
/* ==========================================================================
js/outils.js — Petites fonctions utilitaires, SANS rapport avec Alpine
--------------------------------------------------------------------------
Ce fichier crée un objet global « Outils » utilisé par les autres scripts :
- un stockage sûr (localStorage avec repli en mémoire) ;
- des fonctions de dates ;
- le formatage de l'Ariary ;
- des identifiants uniques.
Séparer ces fonctions « pures » du code Alpine rend le tout plus lisible
et plus simple à tester.
ORDRE DE CHARGEMENT : ce fichier doit venir en PREMIER (avant store.js et
composants.js), car ils s'en servent. Voir la fin d'index.html.
========================================================================== */
const Outils = (function () {
/* ------------------------------------------------------------------
STOCKAGE SÛR
Dans le bac à sable du portail, la simple lecture de
window.localStorage lève une SecurityError. Si on n'attrape pas
l'erreur, tout le script s'arrête ! On garde donc un « plan B » :
un objet en mémoire (perdu au rechargement, mais l'appli marche).
------------------------------------------------------------------ */
const memoire = {}; // plan B : données gardées dans la page
let enMemoire = false; // devient true si localStorage est inutilisable
/** Lit une chaîne enregistrée, ou null si absente. */
function lire(cle) {
try {
return window.localStorage.getItem(cle);
} catch (erreur) {
enMemoire = true;
return Object.prototype.hasOwnProperty.call(memoire, cle) ? memoire[cle] : null;
}
}
/** Enregistre une chaîne. */
function ecrire(cle, valeur) {
try {
window.localStorage.setItem(cle, valeur);
} catch (erreur) {
enMemoire = true;
memoire[cle] = valeur;
}
}
/* ------------------------------------------------------------------
DATES
On manipule les dates sous forme de texte ISO « AAAA-MM-JJ » : c'est
le format des <input type="date">, et on peut les comparer
directement comme des textes ("2026-03-01" < "2026-03-15").
------------------------------------------------------------------ */
/** Met un nombre sur 2 chiffres : 5 -> "05". */
function deuxChiffres(n) {
return String(n).padStart(2, '0');
}
/** Transforme un objet Date en « AAAA-MM-JJ » (heure LOCALE). */
function versIso(date) {
return date.getFullYear() + '-' + deuxChiffres(date.getMonth() + 1) + '-' + deuxChiffres(date.getDate());
}
/** La date d'aujourd'hui au format ISO. */
function aujourdhui() {
return versIso(new Date());
}
/** La date dans « n » jours (n peut être négatif). */
function dansJours(n) {
const d = new Date();
d.setDate(d.getDate() + n);
return versIso(d);
}
/** Vrai si le texte est une vraie date ISO (refuse "2026-02-31"). */
function dateValide(iso) {
if (typeof iso !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(iso)) return false;
const d = new Date(iso + 'T00:00:00');
return !isNaN(d.getTime()) && versIso(d) === iso;
}
/** « 2026-03-05 » -> « jeu. 5 mars 2026 » */
function dateLisible(iso) {
if (!dateValide(iso)) return '—';
return new Date(iso + 'T00:00:00').toLocaleDateString('fr-FR', {
weekday: 'short', day: 'numeric', month: 'long', year: 'numeric'
});
}
/* ------------------------------------------------------------------
DIVERS
------------------------------------------------------------------ */
/** 1234567 -> « 1 234 567 Ar » */
function formatAriary(n) {
const nombre = Number(n) || 0;
return new Intl.NumberFormat('fr-FR', { maximumFractionDigits: 0 }).format(nombre) + ' Ar';
}
/** « Jean Rakoto » -> « JR » (pour l'avatar). */
function initiales(nom) {
const mots = String(nom || '').trim().split(/\s+/).filter(Boolean);
if (mots.length === 0) return '?';
if (mots.length === 1) return mots[0].slice(0, 2).toUpperCase();
return (mots[0][0] + mots[mots.length - 1][0]).toUpperCase();
}
/** Identifiant unique : heure en base 36 + hasard. */
function nouvelId() {
return Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
}
// On expose ce qui doit être utilisable ailleurs.
return {
lire, ecrire, aujourdhui, dansJours, dateValide, dateLisible,
formatAriary, initiales, nouvelId,
/** Vrai si le stockage durable est indisponible. */
get enMemoire() { return enMemoire; }
};
})();