====== JavaScript ====== ===== Memo ===== ==== Traitement des chaînes de caractères ==== === Remplacement des caractères spéciaux === function removeAccents (text) { return text.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); } === kebab-case to camelCase === const capitalizeFirstLetter = (text: string) => text.charAt(0).toUpperCase() + text.slice(1) const kebab2camelCase = (text: string) => text.split('-').map(capitalizeFirstLetter).join('') === Echapement d'une expression régulière === Voir la librairie regexp.escape : https://www.npmjs.com/package/regexp.escape ==== Traitement des tableaux ==== === Tri multicritères === myArray.sort((a, b) => a.firstname.localeCompare(b.firstname) || a.lastname.localeCompare(b.lastname) || a.age - b.age) === Variante === myArray.sort((a, b) => { const compFirstname = a.firstname.localeCompare(b.firstname) const compLastname = a.lastname.localeCompare(b.lastname) const compAge = a.age - b.age return compFirstname || compLastname || compAge }) ==== Traitement des objets ==== === Tri des clés === Object.keys(myObject).sort().reduce( (obj, key) => { obj[key] = myObject[key] return obj }, {} ) ==== Traitement des dates ==== === Formatage === En javascript pur : function formatDate (date) { return `${date.getDate()}/${('0' + (date.getMonth() + 1)).slice(-2)}/${date.getFullYear()} ${date.getHours()}:${('0' + date.getMinutes()).slice(-2)}:${('0' + date.getSeconds()).slice(-2)}` } ==== Gestion des appels successifs ==== === Debounce === Appeler qu'une seule fois une fonction au début ou à la fin d'une succession de déclenchements d'un événement. function debounce (delay, callback) { var timeout = null return function () { if (timeout) { clearTimeout(timeout) } var args = arguments timeout = setTimeout(function () { callback.apply(null, args) timeout = null }, delay) } } window.onresize = debounce(250, function () { console.log('e') }) === throttle === Exécuter une fonction de manière périodique durant la séquence de déclenchements. function throttle(delay, callback) { var previousCall = new Date().getTime() return function () { var time = new Date().getTime() if ((time - previousCall) >= delay) { previousCall = time callback.apply(null, arguments) } } } window.onresize = throttle(250, function () { console.log('e') }) ==== Génération de nombres et chaînes aléatoires ==== === Série de chiffres de longueur donnée === genNumbers (length) { return Math.floor(Math.pow(10, length - 1) + Math.random() * 9 * Math.pow(10, length - 1)) } ==== Gestion des clics et double-clics sur un même élément ==== let clickCounter = 0 let timer: NodeJS.Timeout domElement.addEventListener('click', () => { clickCounter++ if (clickCounter === 1) { timer = setTimeout(() => { clickCounter = 0 // Simple click onSvgNodeClick(node) }, 300) return } else { clearTimeout(timer) clickCounter = 0 // Double click onSvgNodeDblclick(node) } }) ==== Gestion des erreurs ==== === Etendre la classe Error === class DownloadError extends Error { response: Response constructor(message: string, response: Response) { super(message); this.response = response; Object.setPrototypeOf(this, DownloadError.prototype); } }; new DownloadError('Erreur au téléchargement du fichier', response); ==== Manipulation du DOM ==== === Attendre le chargement complet du DOM === window.readyHandlers = []; window.ready = function ready(handler) { window.readyHandlers.push(handler); handleState(); }; window.handleState = function handleState () { if (['interactive', 'complete'].indexOf(document.readyState) > -1) { while(window.readyHandlers.length > 0) { (window.readyHandlers.shift())(); } } }; document.onreadystatechange = window.handleState; ready(function () { // your code here }); === Attendre la présence d'un élément === function waitForElement (selector, callback) { const wait = setInterval(function () { const element = document.querySelector(selector); if (element !== null) { callback(element); clearInterval(wait); } }, 100); } ==== Divers ==== === Mise en surbrillance de text HTML === Avec mark.js highlight (text, search) { if (typeof text !== 'undefined' && text !== null && !!search) { const el = document.createElement('div') el.innerHTML = text const mark = new Mark(el) mark.mark(search, { 'acrossElements': true }) return el.innerHTML } return text } === Fixer plusieurs lignes et/ou plusieurs colonnes d'un tableau === HTML ...
CSS table[data-sticky-rows] th, table[data-sticky-rows] td, table[data-sticky-cols] th, table[data-sticky-cols] td { position: relative; z-index: -2; } table[data-sticky-rows] tr.sticky th, table[data-sticky-rows] tr.sticky td, table[data-sticky-cols] tr th.sticky, table[data-sticky-rows] tr td.sticky { position: sticky; z-index: -1; } table[data-sticky-rows] tr.sticky th.sticky, table[data-sticky-rows] tr.sticky td.sticky { z-index: 0; } Javascript document.querySelectorAll('table[data-sticky-rows],table[data-sticky-cols]').forEach(table => { const options = { rows: parseInt(table.getAttribute('data-sticky-rows')) || 0, cols: parseInt(table.getAttribute('data-sticky-cols')) || 0 }; const tableStyle = getComputedStyle(table); let deltaV = deltaH = 0; // Si le style border-collapse est "separate", il faut en tenir compte if (tableStyle.borderCollapse === 'separate') { const borderSpacing = tableStyle.borderSpacing.split(' '); deltaV += parseFloat(borderSpacing[0]) * 2; deltaH += parseFloat(borderSpacing[1]) * 2; } let top = 0; // Pour chaque ligne du tableau table.querySelectorAll('tr').forEach((row, rowI) => { let left = 0; let totalColspan = 0; // Pour chaque cellule de la ligne [...row.querySelectorAll('th,td')].some((cell, cellI) => { const colspan = cell.getAttribute('colspan'); colspan && (totalColspan += parseInt(colspan) - 1); if (rowI < options.rows) { cell.style.top = `${top}px` } if (cellI < options.cols - totalColspan) { cell.classList.add('sticky'); cell.style.left = `${left}px`; } if (rowI >= options.rows && cellI >= options.cols - totalColspan) { return true; } left += cell.offsetWidth + deltaH; }); if (rowI < options.rows) { row.classList.add('sticky'); top += row.offsetHeight + deltaV; } }); }); === Télécharger des données en provenance d'une variable === function download (data, type = 'text') { const a = document.createElement('a') a.setAttribute('download', 'data') a.href = window.URL.createObjectURL(new Blob([data], { type: type })) document.body.appendChild(a) a.click() a.remove() } const data = Array.from({ length: 256 }, (_, i) => -128 + i) .sort(() => Math.random() - 0.5) .join("\n") download(data)