#21036

HTML Drag and Drop API - Web APIs | MDN

(ceci est une note à moi-même)

Y a des subtilités dans cette API.
La DOC est très claire, mais faut quand-même faire gaffe.

Premier truc : un élément n’acceptera un "drop" (et l’événement "ondrop" ne se lancera) que si l’élément a un "onDragEnter" ET un "onDragOver". S’il n’a pas les deux, ça ne marchera pas.

Ensuite, ne confondez pas les variables :
– event.target : l’élément qui reçoit l’événement (le clic)
– event.currentTarget : l’élément à qui sont attachés les gestionnaires d’événements.

C’est subtil.

Imaginez un SPAN dans un DIV.
Le div est draggable, mais pas spécialement le span. On peut clic sur le span et commencer à le bouger. Dans ce cas, e.target sera le span, mais le vrai élément à considérer sera e.curentTarget, le div (car c’est lui — et son contenu, le span) qui est draggable.

C’est à utiliser aussi lors du drop.

Si on a un UL avec plein de LI que l’on drag-and-drop, il ne faudrait pas que l’on se retrouve avec un UL > LI > LI parce qu’on a drop un LI sur un LI, alors que la dropzone c’est le UL.

~

https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API

#20901

VanillaJS logaritmic HTML5 range input - CodePen

C’est fou que les standards HTML ne permettent pas ça :o

Il y a l’élément <input type=range> qui permet d’avoir un slider/curseur pour choisir une valeur, mais il n’y a pas de possibilité de choisir l’échelle (log, par exemple).

Ici c’est chose faite simplement en JS, même si c’est loin d’être parfait.

https://codepen.io/lehollandaisvolant/pen/XWVWjXd

#20612

Wesley Aptekar-Cassels | Reasons to avoid Javascript CDNs

Tiens c’est vrai ça : l’argument du « une lib à télécharger pour tous les sites » ne tient plus du tout depuis que les navigateurs mettent chaque site dans un sandbox à part maintenant.

(sans compter que y a pas deux sites sur Terre avec les mêmes versions des lib qu’ils utilisent…)

Bref, hébergez tout vous même.

https://blog.wesleyac.com/posts/why-not-javascript-cdn

#20543

Developer Tools secrets that shouldn’t be secrets | Christian Heilmann

Parce qu’il n’y a pas que « console.log() » dans la console d’un navigateur, mais aussi console.warn(), console.trace() ou encore console.table()…

Je n’en connaissais pas la moitié, beaucoup de choses pourraient être pratiques.

https://christianheilmann.com/2021/11/01/developer-tools-secrets-that-shouldnt-be-secrets/

#20490

GitHub - FiggChristian/FontTeX: A JavaScript library that renders HTML math equations in any font family using TeX.

FontTeX, un lib pour faire du LaTeX dans les pages web. Il fait le même boulot que MathJax ou KaTeX.
Voir : https://figgchristian.com/projects/fonttex/home

Le truc c’est que FontTex ne s’emmerde pas à inclure des tas de polices d’écritures « serif » pour styliser les équations. FontTex permet de faire les équations dans n’importe quelle police. Ça fait un peu moins fancy, mais il suffit de les mettre en "serif" ou "times" et ça devient beau. Ou alors d’inclure une unique police web (étendue au latin, grec, etc. néanmoins) et ça restera toujours bien plus léger que KaTeX et MathJax :

– FontTeX : 1 fichier, 300 ko
– KaTeX : 86 fichiers, 3 100 ko
– MathJaX : 700 fichiers, 5 800 ko

Notez que pour KaTeX et MathJax, il y a beaucoup de fichiers de police et tous ne sont pas forcément téléchargés pour faire un rendu. Ça n’empêche pas que l’unique fichier fonttex.min.js soit moins gros que katex.min.js.

Il se peut que je teste ça sur Couleur-Science (où j’utilise actuellement KaTeX).

(Merci beaucoup à Sick pour le partage)

https://github.com/FiggChristian/FontTeX

#20431

Note : JS, dataset et typage pourri

Quand on utilise les attributs « data-* », JS le récupère toujours sous la forme d’une chaîne de caractères, même si ça contient un nombre :

// <div data-nb="12"/>
div.dataset.nb; // contient « "12" », pas « 12 ».

Une façon de s’en convaincre :

div.dataset.nb += 2; // <div data-nb="122"/>

car "12"+2 = "122".

Par contre, si au lieu de faire une addition, on fait une soustraction, alors là il le transforme en nombre puis fait l’opération. Car si une chaîne + chaîne résulte en la concaténation des chaînes, les soustractions de chaînes il ne sait pas faire : la soustraction ne concerne que des nombres, d’où le .parseInt() implicite.

div.dataset.nb -= 2; // <div data-nb="10"/>

Une solution peut-être :

div.dataset.nb = div.dataset.nb+2.

Mais c’est pas joli, pas efficace, ni propre quand l’expression est un peu longue (avec des querySelector partout).

Du coup, une petite astuce :

div.dataset.nb -= -2; // <div data-nb="14"/>

Tout bêtement :-)

ÉDIT :
Et un autre truc tout con, quand on veut transformer une variable de 1 à 0 ou de 0 à 1.
Au lieu de faire ça :

if (var == 1) {
   var = 0;
} else {
   var = 1;
}

Faites ça :

var = 1-var;

Ça fait la même chose :
— si var vaut 1, alors le résultat sera 1−1, donc la nouvelle valeur sera 0.
— si var vaut 0, alors le résultat sera 1−0, donc la nouvelle valeur sera 1.

Si vous utilisez les booléens :

var = !var;
https://lehollandaisvolant.net/?mode=links&id=20211001171736

#20255

Traduire une date - le hollandais volant

JavaScript contient une solution d’internationalisation assez puissant, qui permet de détecter la langue d’un texte ou de formater une date, un nombre…

Ici, j’utilise tout juste 10 lignes de JS pour capter une date entrée par l’utilisateur et la traduire dans la langue qu’il souhaite.

J’ai mis une liste immense de codes de langues, mais beaucoup ne sont pas supportées. Je vais peut-être faire un filtre pour les virer dynamiquement.

En attendant, vous pouvez essayer des langues un peu communes : anglais, allemand, danois… Même le perse, l’arabe ou le japonais sont supportés !

Et ça formate la langue correctement, avec les majuscules, les vigules et l’ordre tout comme il faut. Actuellement il n’y a pas les variantes (pour l’anglais, par exemple j’ai juste « anglais », sans distinguer anglais UK et anglais US).

J’étofferais ça probablement un jour, peut-être avec les émoji de drapeaux, etc. pour faire joli.

ÉDIT : on me signale qu’iOS aurait du mal avec cette page et affiche des "invalide date" partout. Je regarde ça dès que possible, mais comme c’est des fonctions internes à JS et au navigateur, il n’est pas garanti que je puisse trouver une solution. Au mieux je pourrais alors mettre un message de non support de la fonction dans le navigateur.

https://lehollandaisvolant.net/tout/tools/ln-date/

#20209

Spectrographe audio - le hollandais volant

Plus intéressant : le spectrographe d’une chanson.
Là aussi, avec un minimum de code.

C’est particulièrement joli avec des fichiers audio issus de fichier MIDI (comme ceux de vieux jeux vidéos – voir là).

Essayez aussi des morceaux de piano/classique, de métal, ou d’autres genres pour voir les différences. C’est très joli à voir. Ça fait des images sympa.

Au passage, il est possible de cacher des images dans des fichiers audio de cette manière, de façon plus ou moins subtile, plus ou moins audible dans l’audio finale.

(PS : ceux qui ont déjà joué au Konami sur mon site — ou sont en train ;) — savent où je vais cacher mes prochaines énigmes ;)).

(PPS : le code est également mis là : https://codepen.io/lehollandaisvolant/pen/GRmjKzd )

https://lehollandaisvolant.net/tout/tools/spectrum/spectrograph.php

#20194

Loading and playing a sound with the Web Audio API

Les API JS/HTML5 sont vraiment très puissantes.

Ici, on balance un MP3, et ça analyse le flux en direct. Le son est joué, mais l’analyse est dirigée vers une fonction et un canvas qui en trace le spectrgramme.

Autre exemple : https://codepen.io/ZachSaucier/pen/MbdoqQ?editors=0010
On donne un MP3 (ou autre) et ça trace le spectre en direct comme les visualisations dans un lecteur audio un peu fancy.

Encore un exemple : https://mdn.github.io/voice-change-o-matic/
Utiliser le son du micro pour l’amplifier, le déformer, le filtrer… ou appliquer n’importe fonction dessus.

~

De ce que j’ai compris de cette API, c’est qu’elle fait le lien entre des sources audio (micro, mp3…) et des destinations (haut parleurs — peut-être un fichier aussi ?).

On peut, si l’on veut, utiliser un analyser() en direct branché sur le buffer/flux audio. Cet analyser contient les données audio (le spectre en fait, dans un tableau). Dans le deuxième exemple ici, on envoit directement le tableau des fréquences sur un canvas. Ça prend une boucle for() et quelques lignes (en faisant abstraction de la grosse lib qu’il utilise).

Dans l’exemple de déformation de la voix, la « source » est le micro, mais la « destination » est null. On récupère dans un premier temps les données analysées. ces données sont déformées par un algo quelconque de déformation de la voix (bass boost, réverbération, mais on peut imaginer une voix d’alien ou de chipmunk). C’est ensuite cette voix déformée qui est balancée dans une « destination », c’est à dire le haut parleur.

La destination peut également être envoyée sur le réseau dans un flux WebRTC. On peut donc appeler quelqu’un avec une voix déformée (façon "grand méchant qui demande une rançon").

Pas mal non ?

J’ai mis du temps à comprendre tout ça, mais en simplifiant au maximum les différents scripts (et surtout en cherchant à les mettre à jour car les 3/4 des spéc et des scripts sont dépréciées…), je vais produire un petit outil en ligne pour tracer le spectre d’un fichier audio :-)

Et un pour le spectrographe aussi.

Faut savoir que 10 % de mes outils me servent tous les jours (comme de déminifier de code, ou le décodeur Base64), mais les 90 % me servent surtout à me familiariser avec les différentes techno HTML5/JS.

À chaque fois que je vois un truc sympa dans une page web, je suis toujours déçu car le code source est un bordel rempli avec 5 libs et des tas de dépendances. En épluchant la doc, ce que ces pages font en 5 Mo, je cherche à le faire en 50 lignes, sans lib, uniquement en pure-JS.

Par exemple, pour tracer le spectre d’un MP3, je l’ai fait en moins de 100 lignes.
Reste à ajouter quelques éléments d’UI et ça sera bon.

http://www.smartjava.org/examples/webaudio/example4.html

#20117

Create Conway's Game of Life in JavaScript - JavaScript Tutorial | Spicy Yoghurt

Hi,
I can’t seem to find how to leave a comment on your blog (the comment forms doesn’t show for some reason).

I just found a major way to improuve the performance of your script, that makes it run like 10 times faster, allowing it to run a grid of 200x100 every 50 ms or so.

What your script does is redrawing every single cell on everyloop. This is not required. You can only redraw the cells that have actually changed.
In the begin, about 50% or cells are alive, the rest is dead. As the gave evolves, many more cells are dead, and they remain dead most of the time, not changing theire state between most loops.

Just add a cell.redraw() when changing the .alive to the .nextAlive :

Instead of :

// Apply the new state to the cells
for (let i = 0; i < this.gameObjects.length; i++) {
    this.gameObjects[i].alive = this.gameObjects[i].nextAlive;
}

Do :

if (this.gameObjects[i].alive == this.gameObjects[i].nextAlive) {
    this.gameObjects[i].redraw = false;
} else {
    this.gameObjects[i].redraw = true;
    this.gameObjects[i].alive = this.gameObjects[i].nextAlive;
}

And in the draw() :

Replace :

// Draw a simple square
this.context.fillStyle = this.alive?'#ff8080':'#303030';
this.context.fillRect(this.gridX * Cell.width, this.gridY * Cell.height, Cell.width, Cell.height);

With :

if (this.redraw) {
    // Draw a simple square
    this.context.fillStyle = this.alive?'#ff8080':'#303030';
    this.context.fillRect(this.gridX * Cell.width, this.gridY * Cell.height, Cell.width, Cell.height);
}

This way, you will only redraw the cell (and invoke very costly canvas2D calls) when its needed.

In my instance of your script, I also change every for() loop from :

for (let i=0; i<array.length; i++) { … }

to

for (let i=0, len=array.length; i<len; i++) { … }

This avoids calling a (very) costly array.length() at each loop. Now it’s only called once.

I know nobody cares about performance theses days, but well… I do, I this makes you script much faster. As I said, I can go fullscreen on a 4K screen with 10px cells and still refresh every 50 ms, and on a Intel Integrated Graphics chip.

See it alive here : https://lehollandaisvolant.net/tout/tools/life/

https://spicyyoghurt.com/tutorials/javascript/conways-game-of-life-canvas