Comme toujours, le bookmarklet vous permet d'envoyer l'URL courante à Stamp: ouvrez l'image dans un nouvel onglet et cliquez sur le bookmarklet.
pour les plus observateurs
Bande de coquins, vous avez sans doute remarqué un autre bookmarklet à côté du premier... c'est un bookmarklet dynamique: grâce à lui vous pouvez créer des bookmarklets avec un texte spécifique.
Par exemple, si vous envisagez d'utiliser souvent le tampon «dans ton cul», pourquoi le retaper à chaque fois ? Glissez ce lien dans la barre de favoris et let's the fun begins !
Comme d'hab
Fait à l'arrache, interrompu toutes les minutes mais avec amour, dévotion à l'absurdité du monde et mon ordi.
Tiens, je ne savais pas que la bibliothèque GD avait une fonction imagecreatefromstring() qui permet de créer une ressource image à partir d'une chaîne.
C'est très utile dans le cas où on récupère une image via une URL sur un site et qu'on veut lui appliquer un traitement.
En effet, quand on veut faire ça «normalement», on a recours à imagecreatefrom[FORMAT] (imagecreratefromPng() par exemple), ce qui oblige à connaître l'extension ou au moins le type mime de l'image... et des fois, ça couille : l'URL ne contient pas l'extension ou alors il y a des paramètres GET dedans, bref, ça fait chmir.
Avant, je partais vers la récupération de l'extension du fichier pour appeler la fonction adaptée... c'est chiant, sale et pas parfait comme solution (bugs de nom et besoin de télécharger localement l'image sous forme de fichier)
Ainsi, Gilles me fait passer une adresse de métamoteur de recherche d'ebooks ( https://recherche-ebook.fr/ ) tout en notant que ce serait bien de faire une version qui soit plus propre... (pas de JS, de redirections, de pubs etc..)
écoutez Thérèse, comme la vie est savoureuse, n'est-ce pas...
Il se trouve que je m'étais fait un script dont le but était justement de charger des urls, de les parser, de récupérer et d'organiser du contenu.
Pour faire simple, on crée des «profils» correspondant à une série d'URL avec la regex de parsing et le template correspondants. Il suffit alors d'appeler le profil pour obtenir une page de résultats mise en forme.
Comment ça marche ?
on accède au script : ?p=<profil>
slurp accède au fichier de configuration du profil dans packs/<profil>.php
pour chaque url du pack, il charge la page, la parse, met en forme les données dans le template
Le pack est un array du type:
$packs['<profil>']=[
[
'url'=>'http://urltoparse.com/',
'pattern'=>'REGEX PATTERN with (?<name>..) capture',
'template'=>'<li> HTML Template where data is inserted to : use %name% '
],
[
'url'=>'http://urltoparse.com/',
'pattern'=>'REGEX PATTERN with (?<name>..) capture',
'template'=>'<li> HTML Template where data is inserted to : use %name% '
],
];
Dans le template de chaque url,
on peut utiliser %variable% pour placer les captures regex : (?<title>[^"]*?) ➜ %title%
deux variables sont toujours accessibles:
%ROOT% pour accéder à l'url du pack
%DOMAIN% pour accéder au domaine de cette url (pour compléter une URL relative par exemple)
J'ai ajouté la possibilité de créer un dossier au nom du pack contenant un header et un footer pour qu'on puisse faire un site à partir d'un profil.
packstemplates/<profil>/
J'ai ensuite créé un pack contenant les principaux sites d'epubs, cherché les patterns regex...
Ça fait un moment que je parle de certaines de mes applis au fil de billets ou de commentaires, en particulier de celle que j'utilise au boulot. Un très long billet totalement dispensable destiné à ceux que l'enseignement intéresse (ou les logiciels dans l'enseignement)
Je me suis dit que ça pouvait intéresser des gens de voir avec quoi je taffe.
Les attentes (le pourquoi du comment j'ai décidé de faire mon propre truc)
Tout est venu de l'aspect pour le moins instable et aléatoire des logiciels et environnements proposés dans le cadre de mon boulot que ce soit au niveau du ministère, de l'académie, du département ou même du collège.
1- du problème des évolutions 👎
En gros, on change soit de logiciel soit d'environnement soit de machines à peu près tous les ans ou les deux ans, ce qui induit une certaine appréhension au niveau de la conservation de nos données: les exercices réalisés dans les exerciseurs disparaissent, les données et documents de l'ENT également... bref: c'est du taf inutile à se retaper tous les ans (ou deux ans) 💩
2- du problème des logiciels 👎
Mon autre souci, c'est que les logiciels proposés sont rarement utilisés par ceux qui les codent puisqu'il s'agit d'applis à caractère administratif (appel/cahier de texte etc) ou pédagogiques (exerciseurs / stockage de données / expos etc)
Résultat, l'UI est merdique et il est impossible de faire la moindre opération sans un nombre de clics qui à lui seul justifierait qu'on vire le bureau d'études. Quand tu dois swapper clavier souris trois fois pour juste une case à cocher, on a un problème. 😬
Ce problème vient du fait qu'à vouloir donner la possibilité de réaliser des choses complexes, on complexifie inutilement la réalisation des choses simples... or, on fait plus souvent des cases à cocher ou des cases de texte à remplir que des formulaires insérés dans des vidéos. 😭
3- de mes attentes persos quant aux applis
Pour ma part, j'attends d'une appli destinée aux élèves et aux professeurs que:
Pour les élèves:
la consultation et les exercices se retrouvent sur la même plate-forme et dans des espaces clairs
les élèves n'aient pas à se logger pour pouvoir consulter ou s'exercer ( limiter la friction de travail selon mon adage: «si c'est galère il va pas le faire» 😅)
ça passe partout y compris et surtout SUR LEUR PITIN DE TELEPHONES ! Quand tu vois l'ENT sur mobile, ça te donne des envies de suicide collectif.
que ce soit clair, lisible et simple.
que tous les documents / pdf etc utilisés lors d'un cours soient dispo depuis un seul lien de partage
Pour moi:
pas de perte de temps au moment de mettre en ligne: je copiecolle le lien de partage de mon document dans l'ENT et c'est tout.
pas de perte d'énergie au moment de réaliser les documents et travaux (limiter la friction d'usage selon mon adage «la vie est trop courte pour se faire chier deux heures sur un document»)
mise en ligne rapide et simple des documents (et possibilité de partager des documents sur une page sans la réaliser vraiment: génération auto de la page de partage)
pas de perte de mon boulot: c'est sur mon serveur, pas sur une merde académique hébergée aux USA qui va se perdre ou être fliquée.
pas de flicage ni de moi ni de mes élèves.
rapidité et simplicité de la création d'exercices
Naissance de Documentos
Il s'agit d'une appli en ligne de consultation libre des documents utilisés en cours.
Côté élève, un lien de partage conduit à la page que j'utilise en classe pour faire cours: il a donc toutes les ressources pour revoir la leçon ou récupérer le cours en un seul lien.
Cette même page me permet de mettre une image en plein écran en un clic, de faire plusieurs diapos simplement etc.
Côté enseignant, elle fournit un explorateur de fichiers , un éditeur de pages etc. On peut ainsi créer un nouveau dossier de travail pour les 5ème, y déposer en une fois mp3, images etc, y créer une page dans laquelle on organise le tout et même créer des exercices numériques sans que ça prenne plus de temps de le faire là que de le faire sous libreoffice (souvent, la version papier me prend grave plus de temps que la version numérique en fait 😅)
Ok, mais ça a quelle tronche ton truc ?
La racine de la page d'accueil donne accès à tous les niveaux
et dans chaque niveau, une page unique liste tous les documents disponibles. Quand le prof cherche le document du jour, il peut filtrer en tapant une partie du nom du dossier contenant lesdits documents.
Une fois sur le document, l'élève (ou le prof en classe) a une page claire avec documentation, questions, liens vers les fiches de révision et pdf éventuellement distribué.
L'enseignant peut également ajouter des éléments de formulaire dynamiques permettant de sélectionner, cocher, ordonner, compléter
Vous noterez au passage qu'on peut ajouter un bouton permettant de se rendre directement à un temps T d'une vidéo ou d'un enregistrement, pour guider les élèves.
J'ai ajouté un bouton servant à changer la police de caractères pour l'opendyslexic:
Et côté admin alors ?
Le prof a un filemanager pour créer des dossiers et des fichiers simplement, uploader en glisser-déposer, éditer des fichiers. L'accent a été mis sur la rapidité et la simplicité d'utilisation.
Si on se contente d'uploader sans mettre de page, le lien générera une page complète avec les documents. Sinon, on ajoute une page html qu'on édite ensuite (deux clics)
Tous les fichiers constituant un «document de classe» se trouvent dans le même dossier par défaut: si on crée des sous-dossiers dans celui du document, chaque sous-dossier devient une diapo indépendante générée comme des pages individuelles. Lorsqu'on se rend sur la page de partage, on passera de l'une à l'autre avec les flèches du clavier ou celles apparaissant sur les côtés de l'écran... pas besoin de se faire chmir à créer les diapos, les lier que sais-je.
On a donc: ROOT> niveau> document> fichiers ou ROOT> niveau> document> diapo1>fichiers , ROOT> niveau> document> fichiers>diapo2>fichiers etc.
Et la réalisation d'exercices alors ?
Pour la mise en page, on utilise markdown, donc, du texte brut. Hors de question pour moi de devoir me prendre le chou avec des mises en page compliquées.
Sur ce principe, pas de boîtes de dialogue, de clics multiples pour créer des exos: tout se fait par deux types de «balises» sans lâcher son clavier:
les {{}}
Propres à mon framework perso, je les ai adaptées à Documentos:
pour insérer un fichier à un endroit: {{fichier.ext}} et c'est tout.
pour insérer tous les fichiers d'un type {{*.jpg}}, et si on ne se souvient pas bien du nom {{*moncul.jpg}} fonctionne très bien.
pas de boutons ou balises spéciales selon les documents: documentos se démerde seul... ainsi {{fichier.jpg}} crée une image qui passe en fullscreen au clic, {{fichier.mp3}} crée un lecteur audio, {{fichier.mp4}} crée un lecteur video etc...
on peut ajouter facilement des choses plus poussées en insérant des {{fichier.css}} ou {{fichier.js}}spécifiques.
L'appli offre certaines constantes accessibles de la même façon: {{BLEU}} change le fond en bleu, {{FULLSCREEN}} passe en fullscreen dès le chargement, {{FECHA}} ajoute la date du jour en espagnol...
les []
Les éléments de formulaire sont générés via des commandes gu genre {{app->flashcards("")}} qui ne sont pas super simple à mémoriser ou sexy à voir. Du coup, j'ai créé des aliases plus simples qui utilisent les crochets. Ainsi:
une case texte ? [texte à trouver]
Il faut accepter plusieurs réponses ? [réponse1+réponse2]
une liste déroulante ? [choix 1,choix 2, +bon choix,choix3]
Une case à cocher ? []texte d'une case à ne pas cocher], [+]texte d'une à case cocher]
un verbe à conjuguer ? [conjugaison:llamo,llamas,llama,llamamos,llamáis,llaman]
une phrase à ordonner ? [ordonne:La primera pelota está en la estantería.]
des flashcards ? [flashcards:texteface:textedos;texteface2:textedos2]
Une liste de mots à trouver ? [mots:textefr:texteesp;textefr2:texteesp2]
Un mot avec traduction ? [texte es=texte fr]
Un bouton pour aller au temps T d'un media ? [espana.mp3>0:07] ou [>0:07] si un seul media est présent sur la page.
Un bouton pour stocker les réponses de l'élève ? [envoyer]
Un enregistreur pour les élèves n'ayant pas d'appli d'enregistrement ? [enregistreur]
Le fait de ne jamais quitter le clavier supprime la plupart des clics et la perte de temps du passage entre clavier et souris. ça s'avère redoutable dès qu'on a un peu l'habitude: on ne s'occupe que du contenu sans jamais perdre de temps à chercher comment faire (friction d'utilisation minimale)
Tu as parlé de stocker les réponses des élèves ! ET LE RGPD ? 😱
T'inquiète, mon con de chef m'a suffisamment fait chier avec ça pour que je ne coure aucun risque (faire une recherche sur ce site avec le mot clé «j'abandonne» 😡):
rien n'est hébergé hors serveur,
je n'utilise rien que je n'ai fait moi-même (aucune lib notamment)
les données des formulaires remplis qui sont sauvegardées le sont dans un fichier anonymisé: à aucun moment l'élève ne renseigne son nom et à aucun moment une donnée perso n'est utilisée pour le nommage de fichiers. Quand l'élève a envoyé le formulaire, le site lui donne un code à fournir au prof afin qu'il ait accès à la copie.
J'utilise Documentos depuis 2018 et je le modifie régulièrement. L'utilisation au quotidien est top et lors du confinement, je n'ai pas eu à changer grand-chose pour que le distanciel soit possible... je pouvais fournir presque en temps réel et mes élèves ont pu bosser dès les premières minutes de confinement sans être déroutés et depuis n'importe quel appareil (là où l'ENT était à genoux dès 8:10)
Pas de lien ?!
Je ne fournis pas le code de Documentos pour plusieurs raisons:
c'est codé pour moi, avec mes habitudes... ça peut ne pas convenir à d'autres
c'est fait pour l'espagnol: on peut l'adapter, mais faut coder
il y a toujours des bugs par ci par là: je m'en accommode parce que je n'ai pas le temps de coder plus que ça et que ça ne touche pas le côté élève... mais ce serait chiant pour un autre.
j'ai beau essayer de maintenir la cohérence et la logique du code, le patch à la truelle nécessite de reprendre certains aspects.
pas de lien de démo car les documents fournis aux élèves sont copyrightés et que je ne veux pas d'emmerdes avec les éditeurs de bouquins
Je me suis aperçu que mon plugin Plinstagram faisait des trucs étranges et refusait parfois de poster. Pensant à une erreur d'identification, j'ai repris le code mais rien n'y faisait.
Une fois la ruse très moche appliquée, ça semblait revenu à la normale. Puis j'ai décidé d'aller marcher un peu et j'ai pris des photos dans l'idée de tester à nouveau Plinstagram.
Et là, c'est le drame
J'ai beau tout essayer, pas moyen d'envoyer le post avec les photos... mais curieusement, j'aboutis à une erreur 404 et pas à une erreur d'exécution.
Je me dis que ça doit être un problème de taille de formulaire et je me rappelle que, comme un con, j'ai omis de virer l'input files du formulaire avant envoi.
J'explique rapidement comment fonctionne Plinstagram:
Côté JS
1 - l'utilisateur sélectionne des photos sur son ordinateur
2 - pour chaque image, le script js se charge de:
récupérer les images sélectionnées,
créer une miniature avec un canvas
stocker l'image réduite sous forme de donnée base64 dans un input hidden (avec le nom de fichier dans un autre input hidden) créés à la volée
Ainsi on obtient un $_POST[data] et un $_POST[filename] qui contiennent chacun un tableau avec les données de chaque image pour l'un et le nom de chaque image pour l'autre.
Quand on poste, le script vire l'input file pour éviter l'upload de grosses photos.
Côté PHP
Vient ensuite le hook AdminArticlePrepend de la page core/admin/article.php vers laquelle pointe le formulaire de plinstagram: celui-ci se charge de :
1 - parcourir l'array des images redimensionnées postées en base64,
2 - récupérer le nom de chaque image
3 - sauvegarder localement chaque image dans un sous-dossier dédié à l'article
4 - générer une galerie qu'il ajoute au corps du post
5 - finaliser la création des données de l'article.
À ce moment-là pluXML reprend la main et s'occupe du stockage de ces données.
Quand je teste en distant (sur WDD)
Avec une photo, tout se passe normalement. Si j'en mets ne serait-ce que deux, pluXML me renvoie à la page 404, comme si l'URL était fausse: or, il n'en est rien ! L'URL de la barre d'adresse est la bonne, celle du formulaire aussi... pourtant, avec plus d'une photo, la requête n'arrive jamais à core/admin/article.php
Pire, une fois sur la page 404, si je clique dans la barre d'adresse puis que j'appuie sur entrée, j'arrive sans encombre à la page voulue (mais sans les données de formulaire bien entendu): l'URL est donc bonne.
J'ai pensé à une redirection foireuse mais la seule redirection qui reste est celle qui se fait AVANT le formulaire et seulement dans le cas où l'utilisateur n'est pas connecté.
Et puis ça ne semble pas être la faute de mon script PHP vu qu'on n'arrive même pas jusqu'à lui (j'ai collé des exit('moncul'); partout pour voir et rien !)
Quand je teste en local... ô surprise!
TOUT FONCTIONNE SANS PROBLEME ! (le fameux «ça marche sur mon ordi»)
J'ai pensé à un problème de version de PHP: j'ai essayé de changer et c'est pas ça
j'ai songé à une limite de la taille de fichiers ou la limite de taille de post... c'est pas ça (puis ça générerait une erreur, pas un pseudo 404)
Pour résumer
Conclusion
J'en suis à me dire qu'il doit y avoir un genre de restriction pour la taille des données contenues dans des inputs et que cette restriction ne doit pas être la même en local.
Une autre piste que je dois explorer est une éventuelle incompatibilité entre deux plugins... Mais je vois pas lesquels et pis là, faut que j'aille pleurer d'abord.
EDIT dix minutes plus tard:
Tiens, la différence entre le local et le distant, c'est la configuration du rewrite URL dans pluXML: activée en distant. Je mets sur OFF et là, j'obtiens une erreur 406:
Not Acceptable: An appropriate representation of the requested resource could not be found on this server.
Pas bête du tout ça: quand on met en place un cache en PHP, on crée le contenu s'il n'existe pas ou on le lit puis le renvoie s'il existe.
Grâce à un .htaccess bien placé, on peut servir directement le fichier s'il existe et on renvoie vers la page php censée le générer s'il n'existe pas (erreur 404)
Du coup, on n'exécute du PHP que si le contenu n'existe pas.
Merci SebSauvage (et le Duke ) pour cette page dans laquelle je découvre que PHP propose levenshtein() en natif pour calculer la proximité entre deux chaînes...
En ce qui concerne la réducton phonétique, c'est pas forcément simple, en effet (surtout pour le français ) !
Pour un jeu de rôles que j'avais fait quand j'étais jeune (au tout début du jurassique), j'avais fait un petit algo de «traduction» dans la langue du jeu et ça passait par une réduction phonétique puis par une substitution de voyelles apparentées ou de consonnes apparentées, ce qui donnait toujours quelque-chose de prononçable...
Le confinement nouveau est arrivé et avec lui plein de nouvelles raisons de se poser des questions exitentielles (non, j'ai pas fait de faute) (GAG)
Pour y répondre et vous guider dans vos choix, plutôt que de vous fier aux oracles, haruspices et autres politiciens qui vous noieront sous des mensonges, des billevesées voire même des promesses électorales, pourquoi ne pas utiliser la bonne vieille 8 ball magique ?
Du coup, je vous en propose une. Sous forme d'API. Oui.
Bon, on ne m'enlèvera pas de la tête que c'est pas super intuitif, ni super simple, mais bon, je n'ai trouvé que ça qui fonctionne...
Mon souci
Je crée une image côté navigateur avec canvas
je veux l'envoyer à mon serveur pour stockage
On pourrait croire que c'est simple, hein... ben j'ai pas trouvé, personnellement.
J'ai essayé
de transformer le canvas en blob et de l'envoyer via un formdata
de transformer le canvas en blob et de l'envoyer comme un objet simple
de transformer le canvas en DataURL et de l'envoyer via un formdata
de transformer le canvas en DataURL et de l'envoyer comme un objet simple
Mais à chaque fois, j'ai pas été foutu de récupérer les données côté PHP (bon, je me doute qu'il doit y avoir un pacson de trucs que j'ignore encore, hein...)
Ensuite, j'ai pensé
«et si je passais les données au format base64, je devrais pouvoir les récupérer facilement...» car je pratique couramment un optimisme ridicule au sujet duquel il m'arrive encore de sombrer dans la stupéfaction à grand fracas...
Dont acte: je recommence à farfouiller avec des fetch, des posts pis tout mais sans succès: les données décodées font une image invalide.
en désespoir de cause
Je décide de procéder moins élégamment: je copie les données vers un formulaire caché que je poste en target blank pour pas perdre ma page de travail... Oui, je sais, c'est sale, c'est moche, c'est pas secure, j'en ai conscience, c'est pas la peine de m'enfoncer, j'ai déjà assez honte comme ça...
Je reçois bien de la base 64, je décode... Et l'image n'est toujours pas valide. Puis une recherche m'apprend qu'il faut virer l'en-tête base64 côté serveur avant de décoder pour que ça fonctionne...
Un excellent article, très simple d'accès. Résumé pour mémoire mais je vous conseille d'aller lire le tout tant c'est clair et bien documenté:
1.Tout typer
... pour pouvoir compter sur le type des données
Les paramètres des fonctions function moncul(string $str) pour éviter de vérifier les paramètres puisqu'un type erroné provoquera une erreur
Les valeurs de retour des fonctions function moncul(string $str): int car en cas de retour d'un autre type, il y aura erreur. (pour les fonctions ne retournant rien, :void )
Les propriétés de classe : private int $mon_cul; pour qu'une erreur se déclenche en cas d'initialisation d'un type erroné.
2.Protéger ses classes par défaut
ajouter «final» à la déclaration de classe final class monCul(){ pour éviter tout héritage, même fortuit.
laisser ses propriétés en private par défaut
laisser ses méthodes en private par défaut jusqu'à ce qu'on ait besoin de les appeler de l'extérieur
3.Utiliser les comparaisons strictes
... pour éviter les confusions false/0 etc
4.Se passer des «if»
En utilisant l'opérateur ternaire condition ? valeur retournée si true : valeur retournée si false;
Pourquoi ? Parce que c'est plus court mais aussi parce qu'on peut placer la condition directement dans une assignation ou à la place d'un paramètre: $count += ($value === CONTROL_VALUE) ? 1 : 0;
Par contre, je trouve qu'on y perd BEAUCOUP en lisibilité et en organisation.
$intersection = array_intersect(...$bigArray); au lieu de $intersection = array_intersect($bigArray[0], $bigArray[1], $bigArray[2]); // Etc.
8. Toujours ajouter un compteur de boucle pour sortir des while
Ça m'a rappelé un épisode de BigBang Theory dans lequel Sheldon est prisonnier d'une boucle dans son algorithme HowToMakeANewFriend... (c'est Howard qui l'en sort en implémentant un compteur comme condition de sortie).
$block++;
if ($block > 1000) {
break;
}
9.Utiliser les fonctions liées aux tableaux
Je plussoie vigoureusement ce point particulier
Avant de se lancer dans un traitement de tableau en créant une fonction ou une méthode exprès, relisez la doc de toutes les fonctions commençant par Array_ ... histoire de ne pas réinventer la roue.
10.Manipuler les tableaux avec les callbacks et les Collections
Pour manipuler un tableau, penser à utiliser array_map plutôt que foreach si c'est possible:
utilisation simple array_map('trim',$tableau)
fonction anonyme ```array_map(function($k){ code de traitement },$tableau);
avec une méthode array_map(array($instance, 'methode'), $tableau)
Ainsi, il suffit d'utiliser la fonction «afficher l'image» de votre navigateur puis de cliquer sur le bookmarklet pour entrer le texte du meme et récupérer l'image générée.