Révision nth-child
test CSS
Outils à maîtriser
Les événements
Apprenez à déboguer du code sur un événement !Espace de travail
Éditeur et débogueur : un même espace de travail.let !== var
Nous allons au travers de la déclaration d'une boucle remarquer une différence fondamentale entre la définition d'une variable avec var et let.
var permet le Hoisting et let a une portée par bloc {}.
var arr = [],
i = 0;
arr.push(() => i); // équivalent à arr.push(function(){return i});
console.log( arr[0]() ) // exécution de la fonction anonyme
Étudiez ce code
var permet le Hoisting et let a une portée par bloc {}.
code
On déclare un tableau, qui contient une fonction anonyme (sans nom) renvoyant la valeur d'une variable.
var arr = [],
i = 0;
arr.push(() => i); // équivalent à arr.push(function(){return i});
console.log( arr[0]() ) // exécution de la fonction anonyme
Cas de la boucle
Étudiez ce code
Parcours
Voici quelques codes avec parcours de l'arbre du DOM
Code de base
MAP
REDUCE + es6
Testez vous !
Test1
Test2
test
<p id="para-01">
<span>First span</span>
</p>
<script type="text/javascript">
var p01 = document.getElementById('para-01');
alert(p01.firstChild.nodeName)
</script>
Rappel : element.nodeName donne le nom de l'élément.Que va afficher le code précedent ?
valeur de l'index : reduce
comparez les index dans les cas suivants
[0, 1, 2, 3, 4].reduce(function(accumulateur, valeurCourante, index, array){
console.log(`${index} : ACC= ${accumulateur}, Cour= ${valeurCourante}`);
return accumulateur + valeurCourante;
});
avec une valeur initiale :
[0, 1, 2, 3, 4].reduce(function(accumulateur, valeurCourante, index, array){
console.log(`${index} : ACC= ${accumulateur}, Cour= ${valeurCourante}`);
return accumulateur + valeurCourante;
},1000);
[0, 1, 2, 3, 4].reduce(function(accumulateur, valeurCourante, index, array){
console.log(`${index} : ACC= ${accumulateur}, Cour= ${valeurCourante}`);
return accumulateur + valeurCourante;
});
avec une valeur initiale :
[0, 1, 2, 3, 4].reduce(function(accumulateur, valeurCourante, index, array){
console.log(`${index} : ACC= ${accumulateur}, Cour= ${valeurCourante}`);
return accumulateur + valeurCourante;
},1000);
Afficher le nombre de chaque balise du DOM
Ecrire le code JS qui permet d'afficher le nombre de balises par type !
En action :
Injecter le code dans la console d'une page HTML prise au hasard.
En action :
Injecter le code dans la console d'une page HTML prise au hasard.
allTag=(a=>{let b=[],c={};return _explore=(a=>{for(let c of a.children)b.push(c.nodeName),_explore(c)}),_explore(a),_getWordCnt=(a=>{return a.reduce(function(a,b){return a[b]=a[b]+1||1,a},[])}),c=_getWordCnt(b),_sort=(a=>{let b=[],c=Object.keys(a).sort((b,c)=>a[c]-a[b]);for(var d of c)b[d]=a[d];return b}),_sort(c)});let a=allTag(document.body);for(var b in a)a.hasOwnProperty(b)&&console.log(`la balise ${b} apparaît ${a[b]} fois `);
reduce en action : one more
const promos = [
{ promo: "L3miage", etudiants: ["Dupont", "Whells", "Toto"]},
{ promo: "L2miage", etudiants: ["Dupond", "Pathé"]},
{ promo: "M1miage", etudiants: ["Audu", "Baby"]},
]
const tousEtudiants = promos.reduce(function(prev, curr) {
return [...prev, ...curr.etudiants];
},[]);
console.log(tousEtudiants.sort());
remarque, ... est bien un opérateur utilisé ici pour remplacer la concaténation.
{ promo: "L3miage", etudiants: ["Dupont", "Whells", "Toto"]},
{ promo: "L2miage", etudiants: ["Dupond", "Pathé"]},
{ promo: "M1miage", etudiants: ["Audu", "Baby"]},
]
const tousEtudiants = promos.reduce(function(prev, curr) {
return [...prev, ...curr.etudiants];
},[]);
console.log(tousEtudiants.sort());
remarque, ... est bien un opérateur utilisé ici pour remplacer la concaténation.
classList : mon code
Nous allons écrire une classe JS simulant classList.
JavaScript
Nous allons juste développer la méthode add et donnerons le reste du code à étudier.
Nous savons récupérer les classes associées à un nœud du DOM.
Notons que le type retourné est "string"
typeof(object.className)
Voici les fonctions de base
var t = document.getElementById("f");
var classTab,
classString;
console.log(" type of = " , typeof(t.className));
// string->tab
classTab = t.className.split(" ");
console.log(classTab);
//tab->string
classString = classTab.join(" ");
console.log(classString);
JS Bin on jsbin.com
Nous pouvons tester la présence d'une classe avant ajout
JS Bin on jsbin.com
JS Bin on jsbin.com
JS Bin on jsbin.com
Pour finir, on peut evisager d'écrire l'ensemble des fonctions utiles.
JS Bin on jsbin.com
JavaScript
ptr = object.classListC'est un vrai exercice de programmation.
Nous allons juste développer la méthode add et donnerons le reste du code à étudier.
Nous savons récupérer les classes associées à un nœud du DOM.
HTML | <element class="p" ... > |
---|---|
JavaScript |
|
typeof(object.className)
Mise en place de la fonction add
Pour manipuler (ajouter, supprimer) un string, il est fréquent de transformer le string en tableau pour utiliser les méthodes efficaces sur les tableaux.- transforme string en tableau
- ajoute la class au tableau
- transforme tableau en string
Voici les fonctions de base
var t = document.getElementById("f");
var classTab,
classString;
console.log(" type of = " , typeof(t.className));
// string->tab
classTab = t.className.split(" ");
console.log(classTab);
//tab->string
classString = classTab.join(" ");
console.log(classString);
JS Bin on jsbin.com
Nous pouvons tester la présence d'une classe avant ajout
JS Bin on jsbin.com
Amélioration du code
Cela marche, parfait, mais c'est maintenant que la partie intéressante commence !
- Créer des fonctions pour réutiliser notre code de base
- Introduire des éléments de test
Création de fonctions de base
var classesSeparator = " ";
function splitClasses(classesString) {
return classesString.split(classesSeparator);
}
function joinClasses(classes) {
return classes.join(classesSeparator);
}
function indexInClasses(className, classes) {
if (!className || !classes || !classes.length)
return false;
return classes.indexOf(className);
}
Amélioration du code
Il est foncdemental d'imaginer que ce code va rentrer en conflit avec une autre bibliothèque JS. Imaginer que notre fonction add soit utilisée ainsi add(1,2) ?
Les améliorations consistent
//code
})();
exemple :
var _classesSeparator = " ";
Les améliorations consistent
- Création d'un espace de noms
- Mise en évidence des fonctions internes
- Retour d'un objet pointant sur les fonctions
Création d'un espace de nom
Classes = (function () {//code
})();
Mise en évidence des fonctions et variables internes
Nous marquons ces items avec un _exemple :
var _classesSeparator = " ";
Retour de l'objet
La partie la plus subtile.
Classes = (function () {
...
return {
"add": add
};
})();
Le principe reste simple.
Une fonction anonyme s'auto exécute et renvoie un objet que l'on affecte à Classes.
Classes est un objet qui a un méthode add qui pointe en réalité sur la méthode add que nous avons définie et qui fait appelle à des fonctions internes qui ne sont plus atteignable : TOP !
Pour finir, on peut evisager d'écrire l'ensemble des fonctions utiles.
JS Bin on jsbin.com
DOM : API
Property / Method | Description |
---|---|
element.appendChild() | Adds a new child node, to an element, as the last child node |
element.attributes | Returns a NamedNodeMap of an element's attributes |
element.childElementCount | Returns the number of child elements an element has |
element.childNodes | Returns a collection of an element's child nodes (including text and comment nodes) |
element.children | Returns a collection of an element's child element (excluding text and comment nodes) |
element.classList | Returns the class name(s) of an element |
element.className | Sets or returns the value of the class attribute of an element |
element.cloneNode() | Clones an element |
element.contains() | Returns true if a node is a descendant of a node, otherwise false |
element.contentEditable | Sets or returns whether the content of an element is editable or not |
element.firstChild | Returns the first child node of an element |
element.firstElementChild | Returns the first child element of an element |
element.getAttribute() | Returns the specified attribute value of an element node |
element.getAttributeNode() | Returns the specified attribute node |
element.getElementsByClassName() | Returns a collection of all child elements with the specified class name |
element.getElementsByTagName() | Returns a collection of all child elements with the specified tag name |
element.hasChildNodes() | Returns true if an element has any child nodes, otherwise false |
element.id | Sets or returns the value of the id attribute of an element |
element.innerHTML | Sets or returns the content of an element |
element.insertBefore() | Inserts a new child node before a specified, existing, child node |
element.lastChild | Returns the last child node of an element |
element.lastElementChild | Returns the last child element of an element |
element.nextSibling | Returns the next node at the same node tree level |
element.nextElementSibling | Returns the next element at the same node tree level |
element.nodeName | Returns the name of a node |
element.nodeType | Returns the node type of a node |
element.nodeValue | Sets or returns the value of a node |
element.parentNode | Returns the parent node of an element |
element.parentElement | Returns the parent element node of an element |
element.previousSibling | Returns the previous node at the same node tree level |
element.previousElementSibling | Returns the previous element at the same node tree level |
element.querySelector() | Returns the first child element that matches a specified CSS selector(s) of an element |
element.querySelectorAll() | Returns all child elements that matches a specified CSS selector(s) of an element |
element.removeAttribute() | Removes a specified attribute from an element |
element.removeChild() | Removes a child node from an element |
element.replaceChild() | Replaces a child node in an element |
element.setAttribute() | Sets or changes the specified attribute, to the specified value |
element.setAttributeNode() | Sets or changes the specified attribute node |
element.style | Sets or returns the value of the style attribute of an element |
element.tagName | Returns the tag name of an element |
element.textContent | Sets or returns the textual content of a node and its descendants |
nodelist.item() | Returns the node at the specified index in a NodeList |
nodelist.length | Returns the number of nodes in a NodeList |
en action
JS Bin on jsbin.com
const words = ["Beau", "Balle", "Ange",
"Ananas", "Reduce","Action"];
const alphabetical = words.reduce((a, x) => {
if(!a[x[0]]) a[x[0]] = [];
a[x[0]].push(x);
return a; }, {});
Object.keys(alphabetical).forEach(function (key) {
console.log(` ${key} => ${alphabetical[key]}`);
});
console.log(alphabetical);
const words = ["Beau", "Balle", "Ange",
"Ananas", "Reduce","Action"];
const alphabetical = words.reduce((a, x) => {
if(!a[x[0]]) a[x[0]] = [];
a[x[0]].push(x);
return a; }, {});
Object.keys(alphabetical).forEach(function (key) {
console.log(` ${key} => ${alphabetical[key]}`);
});
console.log(alphabetical);
... un opérateur intérésant
function fx(x,y,z) {
console.log( x, y, z );
}
fx( ...[1,2,3] );
|
function fx(...args) {
console.log( args );
}
fx( 1, 2, 3, 4, 5); //
|
Ici ... propage
|
Ici … rassemble
|
function foo(...args) {
args.shift();
args.push("BOB");
console.log( ...args );
}
foo("denis", "DUPONT");
Autre cas
function fx(x,...args) {
console.log( x, args );
}
fx( 1, 2, 3, 4, 5);
- "DUPONT"
- "BOB"
Autre cas
function fx(x,...args) {
console.log( x, args );
}
fx( 1, 2, 3, 4, 5);
- 1
- [2, 3, 4, 5]
idée : forEach
Amélioration du code
La structuration de valeurs dans un tableau, nécessite une boucle pour réaliser un parcours des valeurs :Affichage
let array = [1, 2, 3];for (let i = 0; i < array.length; i++) {
let current = array[i];
console.log(current); // affichage
}
Imaginons l'affichage des valeurs comme une action.
for (let i = 0; i < array.length; i++) {
let current = array[i];
actionAffichage(current); // affichage
}
Affichage positif
Pour afficher les valeurs positives, il est facile de créer une condition ; la fonction précédente devient.for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current>0) actionAffichage(current);
}
ou
for (let i = 0; i < array.length; i++) {
let current = array[i];
actionAffichagePositif(current);
}
Affichage Négatif
Pour afficher les valeurs négatives, il est facile de créer une condition ; la fonction précédente devient.for (let i = 0; i < array.length; i++) {
let current = array[i];
actionAffichageNégatif(current);
}
Bilans
Pour chaque type d'affichage, il est nécessaire de redéfinir la boucle.Améliorations
Nous allons encapsuler le code de la boucle dans une fonction forEach.Il nous reste à réfléchir sur le passage des actions (positif, négatif ...) comme paramètres.
Ainsi, "afficher quelque chose" peut être vu comme une fonction.Les fonctions étant des variables et comme les variables peuvent être passées en paramètres, on peut passer "afficher quelque chose" à une fonction.
Ainsi, la fonction "afficher quelque chose" sera passée en paramètre à la fonction forEach.
Résumé des codes
Affichage |
function affVal(v){
console.log(`val
tab : ${v}`)
}
|
Affichage Positif |
function AffPositif(v){
if (v>0)
console.log(` val positif : ${v} `);
}
|
Boucle sur le tableau |
function forEach(array, fx) {
for (var i = 0; i < array.length; i++)//for of
fx(array[i]);
}
|
Appel |
forEach(T, AffPositif); |
Appel anonyme |
forEach(T, function (v){
console.log(`-> tab : ${v}`);
});
|
En Action
Fichier code
JS Bin on jsbin.com
Pour aller plus loin !
forEach(filtre(T, EstPositif),affVal)
Définir la fonction "filtre" qui prend en paramètre également une fonction permettant de ne concerner que certaines valeurs du tableau.
Ainsi la fonction affVal ne fait plus qu'afficher, elle ne filtre pas les valeurs.
Ainsi la fonction affVal ne fait plus qu'afficher, elle ne filtre pas les valeurs.
articles : fonctions
Série d'articles sur :
paramêtresfonction en argument
Découvrir les closures
New ES6
les fonctions fléchéesthis et les fonctions fléchées
portée
Exemple de fonctions récursives
Cas du dom
perte du contexteES6
Les pointeurs
callback !
Rappel :
let testCallback = function(val,callback) {callback(2*val, " est égale à 2 fois ", val);
};
let monCallback = function(...arg) {
console.log( ` Le saviez vous : ${arg.join("")} ! `);
};
testCallback( 2, monCallback );
En action
Allons plus loin : la gestion d'erreur.
let racine = function (input, callback){
let result = 0,
square= function (num, callback){
(num>0) ? callback(null, Math.sqrt(num)) : callback(" Le traitement des racines de nombres négatifs n'est pas uniforme ");
},
handleResult = function(error,result){
if (error) {
callback(error); return;}
callback(null,result);
}
square(input,handleResult);
};
racine( 9, function (error,result){
if (error) {console.error(error);return; };
console.log(result);
});
En action
Inscription à :
Articles (Atom)