La méthode standard qui consiste à utiliser querySelectorAll()
est relativement verbeuse et ne permet pas de faire facilement un
forEach() dessus. Cette version simplifiée est un raccourci utile
lorsqu’on doit le faire souvent :
Lorsqu’il y a un champ avec un code ou une URL à copier-coller, ça peut
être intéressant de proposer à l’utilisateur·ice de cliquer pour mettre
l’information dans son presse-papier et le coller ailleurs.
functiondeleteConfirmation(event){if(window.confirm('Are you sure you want to delete this?')){return}else{event.preventDefault()}}
Fermeture automatique
Notez qu’à force de recevoir des notifications, les utilisateur·ices
sont promptes à fermer une fenêtre, aussi rouge soit-elle.
Il peut-être pertinent de demander une confirmation qui demande de
saisir quelque chose comme le fait Github lorsqu’on supprime un
dépôt (il faut taper le nom complet du dépôt concerné).
functionslugify(str){consta='àáâäæãåāăąçćčđďèéêëēėęěğǵḧîïíīįìłḿñńǹňôöòóœøōõőṕŕřßśšşșťțûüùúūǘůűųẃẍÿýžźż·/_,:;'constb='aaaaaaaaaacccddeeeeeeeegghiiiiiilmnnnnoooooooooprrsssssttuuuuuuuuuwxyyzzz------'constp=newRegExp(a.split('').join('|'),'g')returnstr.toString().toLowerCase().replace(/\s+/g,'-')// Replace spaces with -.replace(p,(c)=>b.charAt(a.indexOf(c)))// Replace special characters.replace(/’/g,"'")// Turn apostrophes to single quotes.replace(/[^a-zA-Z0-9-']+/g,'')// Remove all non-word characters except single quotes.replace(/--+/g,'-')// Replace multiple - with single -.replace(/^-+/,'')// Trim - from start of text.replace(/-+$/,'')// Trim - from end of text}
Parfois, on veut pouvoir télécharger un fichier généré dynamiquement en JavaScript, par exemple ici pour transformer un tableau en un export CSV (la récupération des données n’est pas montrée).
Il est possible de définir ses propres loggers pour s’y retrouver plus facilement dans la console.
C’est notamment utile si vous faites une lib ou un module réutilisable.
attr(el,'foo')// récupère l’attribut `foo` de `el`attr(el,'bar','baz')// l’attribut `bar` passe à `baz`attr(el,'quux',null)// retrait de l’attribut `quux`attr(el,[dataFoo:'valueBar',dataBaz:'valueQuux'])// set l’attribut `data-foo` à `valueBar` et `data-baz` à `valueQuux`
Il y pas mal de façon de le faire mais ça revient un peu toujours au même.
J’aime bien que ce soit explicite et que ça prenne soin de retirer l’écouteur de l’évènement à la fin.
functiononload(){// An example of what you might want to do:varroot=document.documentElementroot.classList.remove('no-js')// Do something!// Clean updocument.removeEventListener('DOMContentLoaded',onload)}if(document.readyState!='loading'){onload()}else{document.addEventListener('DOMContentLoaded',onload)}
conststateString=JSON.stringify(appState)// appState is a json objectconstcompressed=compress(stateString)constencoded=Base64.encode(compressed)// Push that `encoded` string to the url// ... Later, on page load or on undo/redo we read the url and// do the followingconstdecoded=Base64.decode(encoded)// same encoded as above, but read from urlconstuncompressed=uncompress(decoded)constnewState=JSON.parse(uncompressed)// Now load your application with the newState
Il faut par contre une bibliothèque de dé·compression en complément, comme pako (la partie compress/uncompress).
Générer des chemins relatifs pour des fichiers statiques de modules⚓︎
L’utilisation de la valeur un peu magique de import.meta.url va permettre de générer une URL relative au fichier JS concerné, ce qui permet de garder les fichiers statiques proches du code.
Intéressant pour une approche composants/modulaire.
On crée un élément template (vs. div), ce qui évite d’exécuter les potentiels scripts inconvenants qui pourraient se trouver dans le HTML transmis. Simple et efficace.
La version consistant à utiliser DOMParser est intéressante aussi :
<scriptid="search-stop-words"type="application/json">["stop","words"]// https://github.com/stopwords-iso/stopwords-fr</script><script>conststopWords=JSON.parse(document.getElementById('search-stop-words').textContent// (1))functionmatchSearch(needle,stack){// Create a regex for each word from the needleconstregMap=needle.toLowerCase().split(' ').filter((word)=>word.length&&!stopWords.includes(word))// See https://stackoverflow.com/a/37511463.map((word)=>word.normalize("NFD").replace(/[\u0300-\u036f]/g,"")).map((word)=>newRegExp(word,'i'))letmatches=falsefor(letregofregMap){matches=stack.match(reg)}returnmatches}</script>
Je documente aussi la logique de mettre les stop words dans le HTML en JSON
puis de les parser pour les récupérer car c’est la manière la plus performante de faire.
Voir aussi cette entrée Python et les suivantes pour avoir la logique côté serveur.