ASTUCE Html & JS : détecter quand on sélectionne un élément d'une datalist

En bossant sur l'appli que j'utilise pour mes cours, j'ai voulu ajouter un accès rapide à un document en tapant le début du nom de dossier dans un input alimenté par une datalist.

Bien entendu, je veux éviter de devoir passer du clavier à la souris plusieurs fois : tape un bout du nom, clique pour sélectionner, appuie sur entrée pour valider...

Donc, il faudrait que la sélection et l'ouverture du document se fasse:

  • quand je tape un bout de nom et que j'appuie sur entrée (il ira chercher le premier de la liste)
  • quand je tape le début, que j'utilise les flèches pour aller chercher celui que je veux et que j'appuie sur entrée,
  • quand je tape le début et que je clique sur le nom du document qui m'intéresse.

Et là, c'est le drame

En effet, autant on peut capturer un évènement sur un input, autant ce n'est pas possible sur les option ou le datalist

Donc, il faut gruger et agissant sur les events de l'input.

Je mets ici ma solution actuelle (c'est le code que j'utilise avec mon framework js perso parce que j'ai la flemme de changer ):

<input type="text" placeholder="accès rapide à un document" list="docs_list" id="input_docs_list">
<datalist id="docs_list">
    \\ici les option qui vont bien
</datalist>

<script type="text/javascript">
    on('keydown','#input_docs_list',function(e){ // ça, c'est mon VanillaJS
        if(e.keyCode==13||!e.key){ 
            // si on a appuyé sur entrée ou que l'évènement n'est pas déclenché par une touche (donc, c'est la souris)
            window.location.replace("?"+e.target.value);
        }
    });

    on('input','#input_docs_list',function(e){
        // celui-ci est pour firefox
        if(e.inputType=='insertReplacementText'){
            window.location.replace("?"+e.data);
        }
    })
</script>

J'ai testé sous Firefox, Chromium et Edge...

https://api.warriordudimanche.net/avatrine/

Après avoir commis BadGit, j'ai récidivé cet aprème avec Avatrine... qui génère un avatar sous forme de lettrine à fond de couleur.

Mais pourquoi me direz-vous ?

Parce que :

  1. j'ai trouvé ça joli quand je l'ai vu je ne sais plus où
  2. j'aime bien faire joujou avec Imagick
  3. je fais ce que je veux

Les paramètres

  • str: la chaîne
  • [color]: la couleur de fond (calculée par défaut avec un hash de la chaîne)
  • [sz]: la taille, 128 par défaut

Pour faire simple

En gros, vous lui passez une chaîne de caractères, genre un pseudo par exemple, et il crée une image avec la première lettre du pseudo sur un fond dont la couleur dépend de la chaîne. Et il fait une rotation de 30° (valeur totalement empirique trouvée au doigt mouillé) sur la lettre pour que ce soit plus joli.

Des exemples

?str=Bronco
?str=Bronco&color=red
?str=Bronco&color=blue&sz=256
?str=Jerrywham&sz=256
?str=Sammyfisher&sz=256

Conclusion

Je sais que j'ai déjà fait des générateurs d'avatars... ( voir sur la page d'API https://api.warriordudimanche.net ROR et Avatomic )

avatar (Ror)
avatomic
et que celui-ci ne servira probablement pas plus que les autres mais bon... c'est cadeau quand même !

Apprendre le PHP : Grafikart - Notes diverses

Comme je ne suis pas chez moi, je profite du fait d'avoir plus de temps pour picorer les videos de Grafikart, toujours aussi pertinentes et compréhensibles. Je me note donc ici quelques astuces intéressantes...

Les fonctions anonymes : https://www.youtube.com/watch?v=xJLwegBM64k

Je connaissais sans tellement les utiliser en PHP à cause du point suivant

utiliser une variable hors scope à l'intérieur de la closure...

où comment Bronco a découvert «use»

$closure=function ($arg1,$arg2) use ($var_exterieure){
    #come on, do something
};

Le routeur : https://www.youtube.com/watch?v=tbYa0rJQyoM

La base : une seule variable $_GET

Comme l'URI ne sera pas complexe, on utilise $_SERVER['REQUEST_URI'] pour déterminer une page à charger à la place d'une variable $_GET un peu moche et sans passer par de l'URLrewriting...

On passerait de ça serveur.com/index.php.p=contact

if ($_GET['p']==='contact'){
    require('contact.php');
}

à server.com/contact

if ($_SERVER['REQUEST_URI']==='/contact'){
    require('contact.php');
}

A intégrer dans mon Helium pour la récup de la page demandée ?

Plus complexe : plusieurs variables $_GET

Il utilise une classe routeur ce qui me donne envie d'essayer d'en faire une simplifiée moi-même afin de pouvoir faire par exemple:

$routeur->toGet('page/user'); pour récupérer dans la variable $_GET les infos de l'URI serveur.com/contact/bronco

👍 glopglop : c'est élégant et propre, on peut injecter les données extraites de l'URI dans la variable $_GET afin d'éviter de modifier trop profondément la logique d'une appli existante.

👎 pasgloppasglop : avec ce système, les infos doivent absolument être dans l'ordre attendu ce que n'impose pas l'usage de $_GET



API - Badgit - I'm baaaad, I'm baaaad...

Histoire de bosser un peu sur l'utilisation d'Imagick (pour lequel je m'étais fait des notes ici 12) j'ai essayé de faire une petite «api» de génération de badges simple.

Objectifs

  • Un script qui permet de faire des badges à une ou plusieurs parties,
  • gestion de la taille de police et de la police,
  • gestion des couleurs,
  • gestion d'icônes

Résultat

On peut appeler l'api directement en précisant les variables suivantes:

  • txt: le texte; s'il y a plusieurs parties, on les sépare par un |. exemple ?txt=trop beau|pas vrai
  • backcolor: la couleur de fond; on peut préciser la couleur de chaque partie en les séparant par | aussi. La notation se fait comme en css (sauf pour le # qu'il faut omettre) ```F00|red|rgba(255,0,0,0.5)
  • textcolor: pareil pour le texte. Par défaut, badgit va choisir le blanc ou le noir afin de maintenir le meilleur contraste.
  • fontsize: la taille de police
  • font: une des fontes installées. Je n'en ai mis que deux pour le moment mais on peut utiliser «courier» par exemple.
  • icon: le nom d'une icône de iconeleon (j'ai d'ailleurs ajouté une option pour copier le nom en question depuis l'api d'icônes.)

Exemples

api.warriordudimanche.net/badgit/?txt=Mon%20super%20badge&backcolor=red&txtcolor=&icon=&font=montserrat.ttf&fontsize=16

api.warriordudimanche.net/badgit/?txt=Mon%20super|badge&backcolor=red|pink&txtcolor=pink|red&icon=&font=montserrat.ttf&fontsize=16

api.warriordudimanche.net/badgit/?txt=Mon%20super|badge|de%20ouf&backcolor=red|pink|maroon&txtcolor=pink|red&icon=&font=montserrat.ttf&fontsize=16

api.warriordudimanche.net/badgit/?txt=Mon%20super|badge%20|de%20ouf%20&backcolor=red|pink|maroon&txtcolor=pink|red&icon=|fontawesome_solid/smile-beam.svg|fontawesome_solid/hand-back-fist.svg&font=montserrat.ttf&fontsize=16

Frontend

J'ai goupillé aussi un petit front basique, histoire de ne pas se taper tout au clavier.

FireShot Capture 026 - Badgit - api.warriordudimanche.net.png

Conclusion

Ça ne servira sans doute à personne mais bon, sait-on jamais

Ceci dit, il y a une classe badge qui peut faire l'affaire quelque part...

Le code est là : https://api.warriordudimanche.net/badgit/?download

Des labels flottants en CSS pur #CodingPartyAtHome 💕🤣🤜🤛😎

Depuis que mon grand est en fac d'info, on a un nouveau sujet de conversation et j'ai ENFIN un interlocuteur dans le domaine à la maison !

Du coup, il arrive le weekend avec les TP qu'il a eus pendant la semaine et me pose des questions sur les difficultés qu'il a.

En ce moment, il commence PHP et CSS/HTML...

On me   nomme ?

Du coup, aujourd'hui, il travaillait sur la page de login pour le projet final, une todolist en PHP+HTML+CSS sans JS.

Il voulait faire des labels flottants parce qu'il avait vu que c'était joli... Comme il découvre le monde merveilleux du frontend, on s'y est mis à deux et on a improvisé un petit cours.

Il a appris les subtilités du ciblage, les pseudo éléments, l'usage de :not() et :has()...

Car OUI  on a réussi des labels flottants en pur CSS.png

TLDR;

Pour la page de démo: c'est par là.

Pour le code : c'est sur snippetvamp.

Petit résumé du problème

En gros, on veut que le label soit dans l'input, comme un placeholder, lorsque il est vide mais que le label reprenne une place normale lorsque l'utilisateur clique dans l'input pour le remplir.

Capture du 2024-03-17 15-15-33.png Capture du 2024-03-17 15-15-57.png
Pour ça, j'ai créé un label contenant un span avec le texte et l'input correspondant:
<label><span>Username</span>
    <input type="text" name="login" value="" placeholder=" " >
</label>

Ensuite, je déplace le span vers l'intérieur de l'input:

label span{
    position: relative;
    top:2em;
    left:24px;
    transition:all 500ms;/* et on fait une transition douce, merci*/
}

Puis on utilise :has() pour cibler le span du label contenant un input ayant le focus.

label:has(input:focus) span
{
    color:grey;
    top:0;
    left:0;
    transition:all 500ms;
}

À ce stade, quand l'utilisateur clique dans l'input, le label glisse vers le haut pour sortir de l'input.

Toutefois, le problème c'est que lorsque l'input perd le focus, le label revient à l'intérieur même si l'input a été complété... et les deux textes se chevauchent hideusement...

Et la,   c'est le drame

La logique voudrait qu'on cible alors le span du label contenant un input vide, genre avec input[value=""] ... sauf que ça ne marche pas car le fait de remplir un input ne modifie pas l'attribut value de la balise input...

Zut flute et   cacaboudin

Heureusement, on peut gruger...

Puisqu'on ne peut pas cibler un changement de l'attribut value, on peut cibler... le placeholder ! Enfin... styler en fonction de la visibilité du placeholder...

Ainsi, en utilisant :placeholder-shown, on peut ajouter une règle de ciblage au CSS précédent:

label:has(input:focus) span,
label:has(input:not(:placeholder-shown)) span
{
    color:grey;
    top:0;
    left:0;
    transition:all 500ms;
}

Et là, les plus observateurs d'entre-vous - qui se demandaient avec une angoisse et un mépris non dissimulés pourquoi j'avais collé un placeholder=" " dans mon HTML - comprennent l'astuce: si le placeholder est visible, c'est que l'input est vide...

Et ça marche, tout est supporté dans la plupart des navigateurs. En plus, c'est léger, ne demande pas une structure HTML alambiquée ou des règles CSS à la mords-moi le zboub...

Si ça peut servir, c'est cadeau

Notes perso JS : usage de fetch()

Je me note ici pour une prochaine fois parce que fetch n'est pas forcément très intuitif...

2 façons d'utiliser fetch :

la plus tendance et élégante : en enchaînant les then()

fetch("index.php", { method: 'POST', body: formData })
  .then((response)=>{
        // on attend l'arrivée de la réponse et on la traite
        return response.text(); // ou response.json();
  })
  .then((text)=>{
         // on attend la fin du traitement de la réponse  et on en traite le contenu
       console.log(text);
  });

la plus lisible (?) : avec async et await

En gros, on crée une fonction asynchrone pour pouvoir utiliser les await.

const fetchAPI = async(URL) => {
    const response = await fetch(URL);  // on attend l'arrivée de la réponse 
    const data = await response.json();  // on attend la fin du traitement de la réponse
    console.log(data)
}
fetchAPI("https://jsonplaceholder.typicode.com/todos/1")

MediaRecorder : Bienvenue dans IE6/7/8

En ce moment je bosse sur l'appli de documents/exercices que j'utilise en cours (cf https://warriordudimanche.net/article1686/lappli-documents-que-jai-codee-pour-taf pour mémoire).

J'implémente toute une nouvelle rubrique et de nouveaux items afin de couvrir le spectre de l'expression orale de façon simple en ajoutant une sorte de labo de langue simplifié.En gros, je veux que le gamin puisse travailler à l'écoute de mots modèles mais également qu'il puisse s'enregistrer et se réécouter simplement et quelque soit le support...

Les frontend qui me lisent voient de suite où ça va couiller (merci les copaines)

Et oui, j'ai codé un truc qui fonctionne très bien, relativement propre et simple, facile à utiliser... sous Firefox, opera, vivaldi, chromium et sous Android.

Hélas, ma solution utilise l'API MediaRecorder qui semble présenter des difficultés sous certains navigateurs, vous devinez lesquels...

J'ai testé sur safari (enfin epiphany passque j'ai pas d'apple sous la pogne, tu te doutes...) et ça refuse de fonctionner, vu que MediaRecorder y est bloqué pour nôôôtre saicuritay...

J'ai ensuite testé sur Edge avec mon portable et ça n'a pas fonctionné... toutefois, quand j'ai installé le deb d'Edge sur mon linux ⬇⬇⬇ ...

Parfois, la vie vous envoie   des épreuves, vous savez...

...là, ça a fonctionné... Mais si ça marche, ça doit venir de Linux et pas de Edge (mauvaise foi inside )

Donc en gros, on revient à des soucis de compatibilité avec le nouvel IE ?! (ouelcome to aoueur fanne tasse tique taïme meuchine !)

Nous voila   revenus aux   joies d'Internet   Explorer ?!

Pourtant, canIuse me dit que ça devrait fonctionner, même sous Safari:

Capture du 2024-01-19 12-02-36.png

Bon, avec le navigateur à la pomme, il y a bien une manip à faire dans la configuration avancée pour les devs qui pourrait débloquer la situation mais je me vois mal demander ça à des élèves qui éprouvent déjà des difficultés non négligeables à discerner la barre d'adresse ou qui peinent - la sueur au front - à taper une majuscule sans passer par la touche de verrouillage...

Allez bouffer   vos morts   micro$oft   et apple
Beut ouate        iz ze   solouchonne ?

Donc, là, pour le moment, rien à faire dans l'immédiat pour utiliser simplement MediaRecorder avec safari ou Edge... j'ai donc opté pour une «solution» temporaire: en cas d'absence de l'API, j'ajoute une classe spécifique et je disable les recorders de la page, puis j'affiche un message d'avertissement avec des liens vers des navigateurs compatibles (firefox et forks en tête)...

Après, j'ai bien trouvé un polyfill qui pourrait faire le job ( https://github.com/ai/audio-recorder-polyfill ) mais je ne l'ai pas testé, c'est un peu lourd à installer et pis... c'est pas moi qui l'ai fait...

Si quelqu'un/e a une idée... je prends...

(...)

PHP - Notes perso sur Imagick, un résumé de pourquoi je vire GD à coups de pompes dans l'oignon.

Allez, pour une fois, j'ai un peu de temps devant moi, je vais éplucher un peu la lib Image magick dont je parlais il n'y a guère...

La base

charger UNE image

Simple: pas besoin de plusieurs fonctions selon le format, il suffit de $images = new Imagick('image.jpg');

charger DES images (et là c'est fort)

Même pas nécessaire de passer par un foreach, on fournit le tableau des fichiers voire directement un glob: $images = new Imagick(glob('images/*.JPG'));

Sauver une image

$im->writeImage('image.jpg');

Faire une miniature

Si on laisse une dimension à 0, les proportions sont conservées (quand tu vois la merde que c'est avec GD !) $image->thumbnailImage(100, 0);

Output une image

header('Content-type: image/jpeg');
$image = new Imagick('image.jpg');
# ici on effectue un traitement puis on sort le résultat
echo $image;

Récupération d'infos sur les images

  • taille $im->getImageWidth() $im->getImageHeight()
  • format $im->getImageFormat()

création d'une nouvelle image

$im->NewImage(largeur,hauteur,couleur de fond);

création d'une couleur

Comme pour GD, il faut créer un objet couleur dans les traitements d'image, mais c'est plus simple qu'avec GD (et plus complet): il suffit de passer une couleur selon les normes CSS. Du coup, la transparence n'est pas gérée par une connerie de paramètre «alpha» mais simplement par ... rgba()... 💖

$couleur=new ImagickPixel("white");
$couleur=new ImagickPixel("#FFF");
$couleur=new ImagickPixel('rgb(255,255,200)');
$couleur=new ImagickPixel('rgba(255,255,200,0.5)');

🆒 ⮕ Ça peut paraître compliqué, mais en fait, dans les fonctions où on est sensé utiliser ImagickPixel, je me suis aperçu qu'on pouvait tout simplement passer une string contenant la couleur css... elles se démerdent seules. 😍

Traitements

Ajouts

  • de bordure ->borderImage(couleur,largeur bords verticaux, largeur bords horizontaux): $im->borderImage(new ImagickPixel("white"), 5, 5);
  • de texte :
  • de stéganographie (cacher un filigrane dans une image) ->steganoImage():

Modification de couleurs

  • sepia ->sepiaToneImage(force) : une valeur raisonnable est 80 (sic)
  • solarisation ->solarizeImage(force)
  • négatif ->negateImage(gris): $im->negateImage(0);
  • niveaux
    • $im->normalizeImage();
    • $im->autoLevelImage();
  • gamma ->gammaImage(niveau) : $im->gammaImage(5);
  • contraste $im->contrastImage(niveau)
  • luminosité et contraste $im->brightnessContrastImage(niveau luminosite, niveau contraste);
  • égalisation $im->equalizeImage()
  • coloriser ->colorizeImage(couleur,opacite) : $im->colorizeImage("red",0.5); 🤬 pas réussi à l'utiliser pour ce test...

Modification de taille et d'orientation

  • redimensionner :
    • ->resizeImage(largeur,hauteur, filtre, flou) : $i->resizeImage(250,0,Imagick::FILTER_POINT,0);
    • ->scaleImage(largeur,hauteur): pas encore compris la différence avec la précédente
    • recadrer ->cropImage(largeur,hauteur,x,y): $im->cropImage(200,200,50,50);
    • 💖 créer une miniature à la taille donnée en recadrant l'image autour du centre ->cropThumbnailImage(largeur,hauteur)
  • retourner :
    • $im->flipImage() pour retourner horizontalement
    • $im->flopImage() pour retourner verticalement
  • pivoter ->rotateimage(color, $angle): $im->rotateImage(new ImagickPixel('#00000000'), 75);

Modifications de qualité

  • modification d'opacité ->setImageOpacity(0-1) : $im->->setImageOpacity(0.3);
  • netteté ->sharpenImage(rayon, deviation,canal):
  • amélioration ->enhanceImage()
  • flou :
    • flou tout court ->blurImage(rayon, décalage): $im->blurImage(5,2);
    • gaussien ->gaussianBlurImage(rayon, deviation) : $im->gaussianBlurImage(5,2);
    • de mouvement ->motionBlurImage(rayon,deviation,angle) : $im->motionBlurImage(5,5,45);
  • réduction du nombre de couleurs ->posterizeImage(nb de couleurs, 0/1) :$im->posterizeImage(5,0);
  • ajout de bruit ->addNoiseImage(type) : `$im->addNoiseImage(imagick::NOISE_GAUSSIAN ); voir les constantes de type de bruit

Modification d'aspect et déformations

  • aspect crayon $im->sketchImage(rayon, deviation, angle);
  • aspect fusain $im ->charcoalImage(rayon, deviation);
  • aspect emboss ->shadeImage(gris, angle, hauteur):
    • $im->->shadeImage(1, 90, 2); # emboss + image grisée
    • $im->shadeImage(0, 90,2) # emboss sur l'image d'origine (couleur)
  • peinture à l'huile ->oilPaintImage(rayon) : $im->oilPaintImage(5);
  • détection de bords ->edgeImage(rayon) : $im->edgeImage(5);
  • vagues ->waves(amplitude,longueur): $im->waveImage( 10, 10);
  • déformation ->distortImage(methode, arguments[],0) : voir les constantes de déformation

interactions d'images

Conclusion

Image Magick me semble particulièrement bien nommée tant les possibilités sont énormes et la simplicité d'utilisation étonnante: on sent une volonté de se simplifier la vie lors de l'utilisation... c'est juste beau.

Je voulais mettre une image de chaque effet dans les descriptions mais:

  1. ça prenait une place de ouf
  2. je préfère reprendre certaines de mes applis/api avec imagick
  3. j'ai plus le temps, les autres arrivent
  4. j'ai la flemme.

[EDIT] En fait, j'ai fait une page de test même si tout n'est pas concluant : http://test.warriordudimanche.net/imagick/

19 licences méconnues et inhabituelles

Tout le monde connaît les licences libres habituelles mais il y en a de moins connues et - souvent - moins compliquées à comprendre : petit florilège...

Les licences les plus libres

La WTFPL

Do What The Fuck You Want to Public License - https://fr.wikipedia.org/wiki/WTFPL

Permet de distribuer avec le même niveau de protection que le domaine public, c'est-à-dire AUCUN.

La Beerware

Beerware licence - https://en.wikipedia.org/wiki/Beerware#License

Faites ce que vous voulez et si un jour on se rencontre et que vous trouvez que mon boulot en vaut la peine, payez-moi une bière.

La Bugroff

No problem Bugroff License - http://tunes.org/legalese/bugroff.html

La réponse à toute question à propos des droits de reproduction ou problème légal est : «Sure, No problem. Don't worry, be happy. Now bugger off»

La DAMAIL

Don’t Ask Me About It License

En gros, faites ce que vous voulez et ne me contactez pas.

La GLWTPL

Good Luck With That Public License - https://github.com/me-shaon/GLWTPL

Démerde-toi, demande pas d'aide et - surtout - ne dis à personne que ça vient de moi...

La Woody Guthrie

The Woody Guthrie Public License

«Toute personne qu'on prendra à distribuer ce livre sans permission se verra considéré comme un super pote parce qu'on en a rien à foutre...»

La DSSL

Demerden Sie Sich License - https://dssl.flyounet.net/licenses/

Littéralement, la Licence Démerdez-vous... Je vous laisse la lire tranquilou pour vous faire une idée: toute tentative de résumé serait une trahison du texte original

«Cette Licence» se réfère à la version 1 de la «Demerden Sie Sich License» (le texte original en français). «Démerder», se réfère au sens de se «débrouiller». A aucun moment «cette Licence» ne vous demandera de vous enduire (vous ou votre œuvre) d'excréments humains (ni même animal). «Œuvre» est aussi appelée «travail» (quelques fois, l'extension «de sagouin» peut lui être apposée), «programme» ou tout autre terme relatif à ce qui a été effectué. Ainsi, une «documentation» ou un «manuel» peut être considéré comme une œuvre. «Auteur» signifie que la personne (ou groupe de personnes), qui utilise «cette Licence», se lave complètement les mains de la façon dont vous utiliserez son œuvre.

L'«Auteur» peut-être considéré comme irresponsable et il incombe à l'utilisateur en priorité de se «démerder» par lui même.


Les licences les plus WTF

La D&R

The Death and Repudiation License

This software may not be used directly by any living being.

En gros, l'usage à toute personne vivante est formellement interdit.

La CDL

Chicken dance license - https://github.com/supertunaman/cdl/blob/master/COPYING

Conditions très exotiques pour cette licence qui régule drastiquement la redistribution des copies du code:

  • à chaque 1000ème copie distribuée au moins la moitié des employés ou personnes affiliées doit écouter «the chicken dance» de Werner Thomas
  • à chaque 20000ème copie distribuée, une personne affiliée doit exécuter la Chicken dance dans une vidéo
  • il est formellement interdit à tout employé ou personne affiliée de prononcer le mot «gazorninplat» en public tant que dure la distribution du produit.

La FCL

The Fight Club Licence - https://github.com/benlk/misc-licenses/blob/master/fight-club-license.md

  • You do not talk about the FIGHT CLUB LICENSE.
  • You DO NOT talk about the FIGHT CLUB LICENSE.
  • If someone says "stop" or goes limp — or taps out — the project is over.
  • Only two developers to a project.
  • One project at a time.
  • No shirts, no shoes.
  • Projects will go on as long as they have to.
  • If this is your first time reading the FIGHT CLUB LICENSE, you HAVE to license your next project under the FIGHT CLUB LICENSE.

La OGPITAL

The Offendo General Pain In The Ass License

L'auteur de toute modification doit redistribuer le travail modifié par un moyen plus contraignant et difficile que celui par lequel il a acquis le code original.

La Licence de Schrödinger

https://github.com/benlk/misc-licenses/blob/master/schrodinger-license.md

Heu, là, je vous laisse aller la voir tous seuls.... passque bobo têtête.

La Bugs

The Bugs License r2 - https://github.com/benlk/misc-licenses/blob/master/bugs-license.md

Pour faire court, c'est pas un bug c'est une fonctionnalité...

  • Bugs in the licensed work are features, to be cherished, documented, and developed upon.
  • Modified works must not include known bugs.
  • Where identified, modified works' bugs shall be fixed.
  • Authors and maintainers of the licensed work reserve the right to pull bug fixes from modified or derivative works without compensation, recognition, or any other reference to the authors of the bug fix.

La ABSL

The Anyone But Stallman License - https://github.com/benlk/misc-licenses/blob/master/stallman-license.md

Je crois que c'est clair...

La Méphisto

The Mephistopheles License - https://github.com/benlk/misc-licenses/blob/master/mephistopheles-license.md

Tu veux redistribuer ?! signe ici... avec ton sang.

La WTFWYEDTHS

Why The Fuck Would You Even Do That Holy Shit Public License - https://git.sr.ht/~boringcactus/gotbruh/tree/main/item/LICENSE.md

Seule restriction : il est définitivement et formellement interdit de refactorer ce logiciel en Python 2.


Les plus utilisables en vrai

La DBAD

Don't be a dick License - https://dbad-license.org/

Une licence qui autorise tout avec pour seule condition de ne pas être un connard (a dick)... l'auteur fournit une liste non exhaustive de ce qu'il appelle être un connard:

  • se contenter de copier et de changer le nom
  • vendre une version non modifiée sans produire le moindre travail
  • Faire des modifications afin d'implémenter du contenu dangereux
  • Faire de l'argent avec et devenir riche sans même soutenir l'auteur
  • etc

L' ACSL

Anti-Capitalist Software License [non «libre»]- https://anticapitalist.software/

Vous voulez partager un logiciel ou un code en interdisant toute exploitation commerciale capitaliste et libérale ? Cette licence permet de restreindre l'usage et l'exploitation à certains types d'utilisateurs:

  • une personne privée travaillant pour elle-même
  • une organisation à but non lucratif
  • une organisation à but éducatif
  • une organisation visant les profits partagés pour tous ses membres
  • si l'utilisateur est une organisation alors tous les travailleurs sont propriétaires et inversement.

La Please

The please public licence - https://web.archive.org/web/20200814151216if_/https://awoo.space/@typhlosion/1433790

L'utilisateur a le droit... de demander la permission et l'auteur a l'obligation d'accepter

Sources :

(...)

Api perso: Fetchit, le bon chienchien du oueb...

Ouate ?

Après avoir fait goofi puis Getlib j'ai codé vite fait une petite «api» destinée à ramener en local n'importe quelle ressource distante... «quelle différence avec getlib ?» allez-vous me demander sur un ton narquois à propos de la cruauté duquel je tairais scrupuleusement tout commentaire.

J'ai eu envie de faire ça car j'en avais assez de passer par le combo

bouton droit sur une ressourcetélécharger envoyer sur mon sitefaire un lien ou une img

Du coup, il suffit d'ajouter l'adresse de l'api à l'url vers la ressource distante... Donc http://insta.com/image.jpg devient par exemple http://api.warriordudimanche.net/fetchit?url=http://insta.com/image.jpg

Fetchit va récupérer la ressource en local et vous servir cette version au lieu de la distante. Comme d'hab' si cette ressource a déjà été récupérée elle n'est pas re téléchargée.

Le deuxième effet kiskool (paye ta réf de vieux) c'est que du coup, comme getlib, ça permet de récupérer toute lib en local et être plus RGPD friendly.

Examples:

  • utiliser directement une image distante : <img src="http:www.distantserver.com/pic.png"/> ➜ <img src="http://api.url.com?url=http:www.distantserver.com/pic.png"/>
  • lien vers une ressource distante : <a href="http:www.distantserver.com/file.pdf"> Link to distant file</a> ➜ <a href="http://api.url.com?url=http:www.distantserver.com/pic.png"> Link to distant file</a>
  • utiliser une lib hébergée sur un CDN distant : <script src="http:www.distantnastyserver.com/lib.js"></script> ➜ <script src="http://api.url.com?url=http:www.distantnastyserver.com/lib.js"></script>

    Con figue ?

    Afin d'éviter que votre server ne se retrouve floodé par des fichiers vidéos 8K à 60 gigots l'unité, il y a une limite de taille configurée dans la constante SIZE_LIMIT, fixée par défaut à 10 Mo.

    Le code ?! c'est... le code.

    Ceux qui aiment farfouiller verront que cette fois, j'ai fait une classe fetchit_class.php qui se charge de tout. Son fonctionnement est tellement simple que je me fissure même pas le joufflu à vous le détailler, démerdez-vous.

    License

    Comme d'hab', c'est cadeau... Utilisez, partagez, modifiez... juste respectez la Dont be a dick licence

    donne le ouade

    Comme tout ça n'a de sens que si on héberge soi-même, vous pouvez récup' le zip qui va bien ici : https://api.warriordudimanche.net/fetchit/?download

    Le mot final

    Mes chers cons-patriotes, non aux fuites de données, vive le oueb libre et participatif et vive la france et bisou !

  • document.execCommand - Référence Web API | MDN

    https://antoineboursin.fr/courses/creez-un-editeur-de-texte-wysiwyg

    La vie est mal faite: je découvre document.execCommand() permettant de faire du richtext dans un élément contentEditable juste quand il est officiellement déclaré obsolète...

    Bon, en même temps, sur stackoverflow, the holy baïbol, certains affirment que:

    1. oui, il est obsolète mais n'a pas d'alternative
    2. execCommand semble requis pour tout navigateur prétendant sortir sur le marché,
    3. son implémentation semble sujette à variations selon le navigateur (le fameux internet explorer syndrome de triste mémoire)
    Mais merde !  Je fais quoi moi ?!

    Javascript: tester la validité des liens d'une page afin de les styler

    Petit bout de code fait à la va-vite dans le but de vérifier la validité des liens d'une page. Mon objectif est de pouvoir à terme montrer automatiquement les liens ne répondant plus sur la page où je regroupe les liens de téléchargement illégal

    Le bout de code actuel

    Dans le code ci-dessous, j'utilise fetch et les promesses pour lancer des requêtes afin de styler les liens testés:

    function checkLinks(nodelist){
        function checkUrl(link){
            return fetch(link).then(function(response){     
                return response.status;
            }).catch(function(error){
                return error.status;
            });
        }
        if (!nodelist){
            checkLinks(document.querySelectorAll('.checkLink'));
            return;
        }
        for (let obj of nodelist){
            if (obj.tagName=="A"){
                checkUrl(obj.href).then(function(response){obj.classList.add("status"+response);});
            }else if (obj.hasAttribute("src")){
                checkUrl(obj.src).then(function(response){obj.classList.add("status"+response);});
            }else{
                checkLinks(obj.querySelectorAll("*[href],*[src]"));
            }
        }
    }
    checkLinks();

    Explication rapide

    Étape 1

    J'ai d'abord fait une fonction qui appelle une URL et renvoie une promesse qui, une fois résolue, renverra le statut de la requête. On y retrouve .then qui renvoie le statut d'une requête qui aboutit et .catch qui renvoie celui d'une requête se soldant par une erreur.

    function checkUrl(link){
            return fetch(link).then(function(response){     
                return response.status;
            }).catch(function(error){
                return error.status;
            });
        }

    Les plus coquinous d'entre-vous me feront remarquer à juste titre que, vu ce que je renvoie, je pouvais me contenter de

    function checkUrl(link){
            return fetch(link).then(function(response){     
                return response.status;
            });
        }

    Ceci dit, en prévoyant les deux cas, je m'autorise à gérer le retour différemment selon si ça aboutit ou pas (par exemple retourner «ok200» ou «error404»

    Étape 2:

    Ce block n'est là que pour simplifier la vie de l'utilisateur en lui évitant de procéder lui-même au querySelectorAll()

    if (!nodelist){
            checkLinks(document.querySelectorAll('.checkLink'));
            return;
        }

    Étape 3:

    Je parcours la nodeList en vérifiant l'URL passée en href (pour les A) ou en src (pour les img par exemple).

    Le dernier cas est celui où l'on souhaite vérifier les liens contenus dans un div portant la classe .checkLink : il suffit d'appeler la même fonction de façon récursive en lui fournissant le nodeList des liens contenus das le DIV en question. (ça permet de vérifier un grand nombre de liens sans avoir à leur ajouter individuellement la classe .checkLink, ce qui est particulièrement utile quand on publie des articles en utilisant markdown )

    for (let obj of nodelist){
            if (obj.tagName=="A"){
                checkUrl(obj.href).then(function(response){obj.classList.add("status"+response);});
            }else if (obj.hasAttribute("src")){
                checkUrl(obj.src).then(function(response){obj.classList.add("status"+response);});
            }else{
                checkLinks(obj.querySelectorAll("a,img"));
            }
        }

    Comment on l'utilise ?

    Il suffit de mettre la classe .checkLink à tout objet dont on veut tester les liens et de coller la fonction dans la page puis de l'appeler via un checkLinks(); de bon aloi.

    En l'état, la fonction ajoutera une classe .status200 pour les liens ok ou .status404 pour les URL qui ne répondent plus.

    Il ne reste plus qu'à styler ces classes en changeant la couleur, le fond ou en ajoutant des emoji avec un petit content. On peut même éventuellement masquer un objet dont l'URL ne répond pas...

    Limites

    Le script étant en JS, il se heurte évidemment aux règles de la politique CORS: toute requête hors du domaine en cours va échouer à moins de redéfinir le CORS dans le Head de la page via

    <meta http-equiv="Content-Security-Policy" content="Content-Security-Policy:..."/>

    Licence

    Comme d'habitude, il s'agit autant d'un proof of concept que d'une truc utile... en tout cas, n'hésitez pas à en faire rigoureusement ce que vous voulez: c'est cadeau...

    API + BOT = RTE_color_bot (@RTE_color@piaille.fr)

    Parfois, un post en entraîne un autre... Ainsi, tu t'es mis à coder un BOT presque par inadvertance - avec les difficultés qu'on connaît - et tu le partages parce qu'il n'y a pas de raison que l'auteur soit le seul à pleurer... pis t'as un copain qui te lit et qui prend le truc au sérieux... en tout cas suffisamment pour te proposer d'en faire un autre !

    Non, c'est vrai ?!    T'AS TROUVÉ ÇA BIEN ?!

    Donc, me v'la reparti pour un tour...

    Objectif de la demande: récupérer les données de l'API RTE tempo ( https://data.rte-france.com/catalog/-/api/consumption/Tempo-Like-Supply-Contract/v1.1 ) pour dire la couleur du jour et celle du lendemain et les poster sur un bot mastodon (mais pouvoir appeler le script comme une API aussi)

    Je suis donc parti pour tester ladite API: pour la faire courte, ça m'a permis - après les galères d'usage - de comprendre comment tout ça fonctionnait (en particulier la demande d'un token, l'appel d'une api en php etc)

    J'en suis arrivé à un script qui produit un texte donnant la couleur du jour et celle du lendemain.

    «Oui, mais ce serait cool...»

    Le texte c'est bien, mais ce serait mieux si on pouvait récup les données en HTML et intégrer ça avec une Iframe, comme un code d'intégration.

    Pis éventuellement en RSS aussi...

    Bon, tant que j'y étais, j'ai aussi fait un mode json, au cas où on voudrait ça dans un frontend à soi...

    Du coup, mon API s'appelle de plusieurs façons différentes:

    • URL seule ➜ retour en texte RAW (prêt à poster)
    • URL?html ➜ retourne le code HTML
    • URL?json ➜ renvoie les données en JSON
    • URL?rss ➜ le flux RSS de l'API
    • (cadeau bonux) URL?embed_code ➜ retourne le code pour mettre ça sur son site avec une iframe.

    Pour faire bonne mesure

    Le script produit un fichier pour chaque type de retour et ne le régénère qu'une fois par jour afin d'éviter de se faire «hammerer» comme dit @parigotmanchot

    Jusque là, tout va à peu près dans un monde couci, couça

    À ce stade, le script fonctionne même si le code est un peu sale et pas bien rangé... il fait ce qu'on lui demande. A part que parfois, il ne donne pas la couleur du lendemain... mais pas en local... juste en distant. Je n'ai pas encore vraiment cherché pourquoi, mais je pense que c'est dû au moment où l'on appelle l'API de RTE.

    Pourquoi s'en tenir là ?

    Tant que j'y étais, j'ai regardé l'API ECOWATT ( https://data.rte-france.com/catalog/-/api/consumption/Ecowatt/v4.0 ) qui donne une couleur et un message décrivant le niveau de stress du réseau.

    Du coup, le script appelle les deux API et retourne les données cumulées des deux.

    ce qui donne ça

    Capture du 2022-12-11 10-47-34.png

    Capture du 2022-12-11 10-49-23.png

    J'en veux j'en veux...

    Si ça vous intéresse, le zip est là : RTETempo.zip et il est distribué sous stricte licence faites-en ce que vous voulez. 😅

    Les constantes au début permettent de configurer un peu:

    • TOKEN_BASE64 : pour mettre votre propre jeton si vous voulez vous inscrire sur RTE (qui accepte les emails jetables type yopmail, je dis ça je dis rien 😬)
    • TEMPO_BEFORE_TODAY, TEMPO_BEFORE_TOMORROW, ECOWATT_BEFORE_TODAY, ECOWATT_BEFORE_TOMORROW : pour définir le texte renvoyé avant la couleur.
    • HTML_STYLE : pour changer le style du HTML généré
    • TEMPO_HTML_TEMPLATE, ECOWATT_HTML_TEMPLATE : pour changer le code HTML à utiliser en cas de retour HTML
    • ECOWATT, TEMPO : deux booléens permettant de débrayer l'un ou l'autre des appels (si vous ne voulez que ECOWATT ou que TEMPO)

    Et le BOT ?!

    Ben j'ai fait un autre BOT pour poster les couleurs du réseau une fois par jour... https://piaille.fr/@RTE_color ( @RTE_color@piaille.fr )

    Capture du 2022-12-11 11-01-14.png

    YoutubeRSS

    Hier, je me suis aperçu que le bookmarklet que j'avais fait pour trouver le flux RSS d'une chaîne youtube ne fonctionnait pas toujours 🤬: en effet, si l'URL de la chaîne n'est pas du type www.youtube.com/channel/xxxCHANNEL_IDxxx ça ne fonctionne pas... Or, les chaînes peuvent être aussi sous une forme dans laquelle le channel_id n'apparaît pas.

    zut flûte et cacaboudin

    Du coup, je m'y mets

    Au lieu de laisser youtube me chier dans les bottes, je me suis dit que, si le channel_id n'est pas dans l'URL, il doit être planqué quelque part dans le html de la page.

    En fouillant un peu, twingo bongo jannielongo bingo 🥳 J'ai trouvé ça en parsant avec (presque) la même regex que pour l'URL.

    con.jpeg

    J'ai donc codé vite fait une «api» qui renvoie l'URL du flux RSS d'une chaîne Youtube dont on fournit l'adresse.

    On peut l'utiliser avec le frontend minimaliste prévu, en faisant une requête GET ou via le bookmarklet qui va bien.

    Le tout est bien entendu utilisable, autohébergeable et modifiable, comme d'habitude

    Allez !

    Fil RSS des articles