Google I/O ’19
Avec par ordre :
private class fields 6:57 Regex matchAll 9:16 Numeric literals 10:19 BigInt formatting 11:50 flat & flatmap 13:23 fromEntries 15:28 Map to Object conversion 16:47 globalThis 19:18 Stable sort 20:00 Intl.RelativeTimeFormat 22:45 Intl.ListFormat 24:29 Intl.DateTimeFormat -> formatRange 26:32 Intl.Locale 27:10 Top-Level await 28:12 Promise.allSettled/Promise.any 31:13 WeakRef 32:30
fonction délégation
Utils.js
function $delegate(target, selector, type, handler, capture) {const dispatchEvent = event => {
const targetElement = event.target;
const potentialElements = target.querySelectorAll(selector);
let i = potentialElements.length;
while (i--) {
if (potentialElements[i] === targetElement) {
handler.call(targetElement, event);
break;
}
}
};
target.addEventListener(type, dispatchEvent, !!capture);
}
Utilisation
$delegate(target,"span","mouseover",show,true)module : en action
Création du fichier helper.js
/*** querySelector wrapper
*
* @param {string} selector Selector to query
* @param {Element} [scope] Optional scope element for the selector
*/
export function qs(selector, scope = document) {
return scope.querySelector(selector);
}
/**
* addEventListener wrapper
*
* @param {Element|Window} target Target Element
* @param {string} type Event name to bind to
* @param {Function} callback Event callback
* @param {boolean} [capture] Capture the event
*/
export function $on(target, type, callback, capture) {
target.addEventListener(type, callback, !!capture);
}
/**
* Attach a handler to an event for all elements matching a selector.
*
* @param {Element} target Element which the event must bubble to
* @param {string} selector Selector to match
* @param {string} type Event name
* @param {Function} handler Function called when the event bubbles to target
* from an element matching selector
* @param {boolean} [capture] Capture the event
*/
export function $delegate(target, selector, type, handler, capture) {
const dispatchEvent = event => {
const targetElement = event.target;
const potentialElements = target.querySelectorAll(selector);
let i = potentialElements.length;
while (i--) {
if (potentialElements[i] === targetElement) {
handler.call(targetElement, event);
break;
}
}
};
$on(target, type, dispatchEvent, !!capture);
}
/**
* Encode less-than and ampersand characters with entity codes to make user-
* provided text safe to parse as HTML.
*
* @param {string} s String to escape
*
* @returns {string} String with unsafe characters escaped with entity codes
*/
export const escapeForHTML = s => s.replace(/[&<]/g, c => c === '&' ? '&' : '<');
Utilisation de la fonction $on dans un fichier
Voici la structure de l'application
avec dans le répertoire src :
Pour utiliser la fonction $on dans app.js on écrit :
import {$on} from './helpers.js';
<script src="src/app.js" type="module"></script>
Serveur
on peut utiliser simplement l'extension sous chrome.
Exemple en ligne
template
Utilisation de template :
/**
*
* @constructor
*/
class Template {
constructor() {
this.defaultTemplate = ` // notez le `
<li data-id="{{id}}" class=""> // notez {{}} un code utilisé pour remplacer la valeur
<div class="view">
<input class="toggle" type="checkbox" />
<label>{{title}}</label>
<button class="destroy"></button>
</div>
</li>
` // fin
}
show = function(data) { //data = [tableau d'objets issus d'une bibliothèque]
let view = ''
for (let v of data) { // v est un objet contenant les informations
let template = this.defaultTemplate;
template = template.replace('{{id}}', v.id)
template = template.replace('{{title}}', v.title)
view = view + template
}
return view // une concaténation de <li>
}
}
let view = new Template();
let li = view.show([{
id: 1,
title: "Hello",
},
{
id: 2,
title: "World",
}
])
// insertion des <li> dans le DOM <ul>
document.querySelector(".todo-list").insertAdjacentHTML("afterbegin", li);
Remarque :
on pourra préférer cette écriture utilisant la méthode reduce sur le tableau items
items.reduce((acc, item) => acc + `
<li data-id="${item.id}"${item.completed ? ' class="completed"' : ''}>
<div class="view">
<input class="toggle" type="checkbox" ${item.completed ? 'checked' : ''}>
<label>${item.title}</label>
<button class="destroy"></button>
</div>
</li>`, '');
RegEXP : en action escape
Considérer le code suivant, permettant d'échapper le code HTML (le texte saisie ne doit pas être interprété en HTML).
let p = '<h1>escapeForHTML<h1>';
let regex = /[<&]/gi;
let r = {
'>' : '>',
'&' : '&',
'<' : '<',
}
let f = function(c){
return r[c];
}
Comparer le résultat des deux écritures :
document.body.insertAdjacentHTML("afterbegin",p);
document.body.insertAdjacentHTML("afterbegin",p.replace(regex,f));
let p = '<h1>escapeForHTML<h1>';
let regex = /[<&]/gi;
let r = {
'>' : '>',
'&' : '&',
'<' : '<',
}
let f = function(c){
return r[c];
}
Comparer le résultat des deux écritures :
document.body.insertAdjacentHTML("afterbegin",p);
document.body.insertAdjacentHTML("afterbegin",p.replace(regex,f));
Version compacte !
const escapeForHTML = s => s.replace(/[&<]/g, c => c === '&' ? '&' : '<');
document.body.insertAdjacentHTML("afterbegin",escapeForHTML("<h1> escapeForHTML </h1>"));
document.body.insertAdjacentHTML("afterbegin","<h1> escapeForHTML </h1>");
Version avec Map
let p = '<h1>escapeForHTML<h1>';
let regex = /[<>&]/gi;
let r = new Map([
['>','>'],
['&','&'],
['<', '<'],
]);
let f = c => r.get(c)
document.body.insertAdjacentHTML("afterbegin",p);
document.body.insertAdjacentHTML("afterbegin",p.replace(regex,f));
Inscription à :
Articles (Atom)