Diaphragme en Iris paramétrable


11 février 2016

En passant...

Ayant eu besoin de rendre paramétrique un "icône" vectoriel pour une mise à jour de Batipad, j'ai intégré tout le code ici, afin que ça puisse servir à quelqu'un (peut-être) et surtout à moi !

Diaphragme

Nombre de feuilles :
Rayon principal :
Rayon secondaire :
Décalage d'angle :
Couleur de fond :
Couleur de bordures :
Style :

JS : Object.observe


22 décembre 2014

Une nouveauté des dernières versions des navigateurs (liste non établie) :

var Test = {
    name:"Nom", prenom:"prénom"
};
Object.observe(Test, function(changes)      {
    $("#observe").append(changes.type+" "+changes.name+" "+changes.oldValue+"<br/>\n");
});
Ceci va donc remplacer, à terme, mon manager qui observe la même chose mais de manière synchrone lui. Ici on est en asynchrone...

Code de Luhn


13 juin 2013

Voici la démo et l'implémentation JS du code de Luhn que j'apprécie pour sa simplicité à vérifier des erreurs de saisie.

Génération du code
Nombre initial :
Résultat :
Validation d'un code
Nombre à vérifier :
Résultat du test :
//Vérifie que le paramètre d'entrée est valide au sens du code de Luhn. Renvoie true ou false en fonction du résulat.
function    checkLuhnCodeValidity(srcNumber)        {
    srcNumber = ""+srcNumber;
    var Total = 0;
    for(var i=0; i<srcNumber.length; i++)       {
        var CurDigit = parseInt(srcNumber[srcNumber.length - 1 - i]);
        if (isNaN(CurDigit))        return false;
        CurDigit = i%2 ? CurDigit*2 : CurDigit;
        if (CurDigit > 9)       CurDigit -= 9;
        Total += CurDigit;
    }
    return Total % 10 == 0;
}
//Renvoie le chiffre, aka le code de Luhn, qu'il faut ajouter à la variable d'entrée pour que l'ensemble soit valide au sens du code de Luhn.
function    computeValidLuhnCode(srcNumber)     {
    for(var i=0; i<=9; i++)     {
        var TestNumber = ""+srcNumber+i;
        if (checkLuhnCodeValidity(TestNumber))      return i;
    }
    return false;       //srcNumber n'est pas un nombre (peut-être la variable contient-elle des lettres ou d'autres codes ?)
}

Minification de fichiers JavaScript


19 février 2013

Le problème

Considérant un dossier de fichiers JS dont un sous-ensemble est quotidiennement modifié, le problème de leur minification se pose : je veux que ces fichiers minimisés puissent être générés automatiquement en utilisant yui-compressor (pour l'instant). En Bash, ça donne :

find . -maxdepth 1 -name "*js" | while read f; do
    [[ `stat -c %Y minified/${f%.js}-min.js` -gt `stat -c %Y $f` ]] && continue;
    echo $f
    yui-compressor --type js --charset utf-8 -v -o minified/${f%.js}-min.js $f;
done 2> minified.log

Le meilleur compresseur

Même si le script précédent fonctionne, YUI-Compressor n'est pas terrible (ou je ne sais pas l'utiliser). Je vais donc m'orienter vers le Google Closure Compiler qui est plus lent à l'exécution (10x) mais BEAUCOUP plus intéressant. A noter que l'on peut utiliser deux modes pour ce minificateur : le mode par défaut (sans option particulière) et le mode ADVANCED_OPTIMIZATIONS, qui donne des résultats très intéressants. Par contre, le code à minimiser/obfusquer doit être adapté. Ainsi, pour utiliser le mode ADVANCED_OPTIMIZATIONS et obtenir ainsi des scripts extrêmement petits et obfusqués, il faut :

  • ajouter, selon le format jsDoc, le fait qu'une fonction est un constructeur : ainsi, elle pourra utiliser "this" sans warning de la part de Google Closure. D'autres types d'annotations sont disponibles.
  • ajouter window["MonConstructeur"] = MonConstructeur;
  • si le code utilise un hash externe il faut utiliser la notation des tableaux a.["nom-du-membre"] plutôt que la notation objet : a.nomDuMembre
  • on n'écrit PLUS JAMAIS :
    MonObjet.prototype = { ... }; MonObjet.prototype.constructor = MonObjet;
    mais on va déclarer une par une toutes les propriétés d'un objet, aussi bien les méthodes que les variables comme indiqué par les 4 points suivants
  • pour les fonctions publiques :
    MonObjet.prototype["NomDeLaFonctionPublique"] = function(...) { ... Corps de la fonction publique ... };
  • pour les fonctions privées :
    MonObjet.prototype.NomDeLaFonctionPrivée = function(...) { ... Corps de la fonction privée ... };
  • pour les variables publiques :
    MonObjet.prototype["NomDeLaVariablePublique"] = ...;
  • pour les variables privées :
    MonObjet.prototype.NomDeLaVariablePrivée = ...;

L'appel au compilateur/minificateur, installé dans mon répertoire utilisateur, se fait avec la ligne ci-dessous, avec $f contenant le chemin du fichier JS à compresser :
java -jar ~/closure/compiler.jar --charset UTF-8 --compilation_level ADVANCED_OPTIMIZATIONS --js "$f" --js_output_file ${f%.js}-min.js

Résultats

...

Véritable type JS


16 novembre 2012

Un post très intéressant de Angus Croll m'a donné envie de m'inspirer de sa fonction permettant de déterminer le type d'un objet JS en utilisant la propriété interne [[class]] (suivant la spec officielle). Ainsi la fonction suivante :

Object.prototype.kindOf = function()        { return ({}).toString.call(Obj).slice(8, -1); }
Object.prototype.isKindOf = function(targetKind)        { return ({}).toString.call(Obj).slice(8, -1) == targetKind; }
Object.defineProperty(Object.prototype, "kindOf", {enumerable:false});
Object.defineProperty(Object.prototype, "isKindOf", {enumerable:false});
//this == global object
this.kindOf = function(obj) { return obj.kindOf(); }

On peut donc l'utiliser comme suit :

if (kindOf(obj) == "Array") ...     //Utilise l'objet global, syntaxe identique à typeof
if (obj.isKindOf("Array"))  ...     //Syntaxe objet incorporant la comparaison
/* ... */
switch (MonObjet.kindOf())      {   //Syntaxe objet
    case    "Object": ...
    case    "Number": ...
    case    "CustomConstructor": ...
    ....
}

A noter que String::slice est beaucoup plus rapide que la RegExp et que la passage en minuscule ne m'apportant rien je l'ai supprimé. Cf mes profiles.

L'abbréviation ({}) en lieu et place de object.prototype est intéressante : un nouvel objet (le {}) utilisera toujours la fonction toString de Object.prototype. Donc on crée un objet temporaire que l'on va utiliser pour accéder à la fonction toString ce qui a pour conséquence : 1) d'ajouter un objet en mémoire 2) de diminuer le nombre de lookups car Object.prototype.tooString entraîne 2 lookups et ({}).toString un seul. Conclusion : moins de temps machine et plus de mémoire instantanée. Du Heisenberg informatique classique...

Et au fait : pourquoi ({}) est l'équivalent de Object.prototype ? En fait, les deux ne sont pas équivalents, seules les références à toString sont identiques, ce que l'on peut vérifier en testant l'expression ({}).toString === Object.prototype.toString. La notation est étrange mais surtout parce qu'il y a des parenthèses autour de l'objet littéral. Pourquoi ces parenthèses ? Parce que si on écrit {}.toString, cette écriture est ambigue : les accolades représentent un bloc de code vide ou un objet littéral ? Un "." juste après un bloc de code vide ne fonctionne pas... On lève cette ambiguité en ajoutant les parenthèses autour des accolades : cette fois il ne peut plus s'agir d'un bloc de code vide.

Accueil1 2 3 4 5 6 7