//script1.js
let email = document.querySelector('#email')
let password = document.querySelector('#password')
let btn = document.querySelector('#btn')
//script2.js
email.addEventListener('keyup', (event) => {
if (!isEmailValid(email.value)) {
console.log('Email is invalid')
} else {
console.log('Email is valid')
}
})
password.addEventListener('keyup', (event) => {
console.log('Password length ', password.value.length)
})
// Vérifie si l'email est correct
const isEmailValid = (email) => {
return email.toLowerCase()
.match(
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
);
}
//script3.js
btn.addEventListener('click', (event) => {
event.preventDefault()
if (isEmailValid(email.value) && password.value.length > 8) {
alert("Form is valid")
} else {
alert("Form is invalid")
}
})
Si votre page HTML fait appel à l’inclusion de beaucoup de fichier JS, vous aurez envie de fusionner tous ces fichiers en un seul pour le rendre plus compact. je vous propose d’utiliser Rollup, qui est simple comparé à Webpack. On va installer Rollup
Un socket est une interface de communication entre deux noeuds dans un réseau informatique. Plus concrètement, entre deux ordinateurs, et pour les développeurs web entre un serveur et un client, aka votre ordinateur et plus précisément le navigateur.
Côté serveur
On va pour simplifier utiliser Nodejs, avec un script en local on va pouvoir en quelques ligne mettre en oeuvre un socket grâce à la librairie socket.io
Côté client
Grâce à une librairie socket.io-client, on va pouvoir se connecter à un socket.
Quelle est la différence entre un socket et une requête AJAX?
Dans le monde du HTTP, une communication entre client et serveur ne dure qu’un instant, entre deux communications il n’y a rien. Vous faites une requête AJAX, le client initie une demande (Request), le serveur réponse avec un Response, et puis c’est fini.
Dans le cas d’un socket, une fois que le client initie une demande de connexion, la communication s’établie et dure tant que l’on n’a pas arrêté, elle ne s’arrête pas toute seule. Le socket sert à maintenir une connexion persistente, avec un flot continu de données de part et d’autre.
Le socket répond au besoin de recevoir contnuellement des données, une application comme une courbe de bourse en temps réel a besoin d’un socket, cela permet une mise à jour temps réel du cours de bourse. Bien sû on pourrait faire toute les secondes une requête AJAX, mais c’est très consommateur de données, de par la nature du protocole HTTP. Socket ne fait pas partie de la technologie HTTP.
Démarrer un projet avec socket.io
Créez un nouveau répertoire de projet, ouvrez le avec VSCode, ouvrez un terminal sous VSCode.
vous pouvez lancer le serveur NodeJS avec la commande:
node index.js
ça va initialiser un serveur qui écoute sur le port 3000 (par défaut pour NodeJS). Si dans votre navigateur, vous ouvrez l’url http://localhost:3000. Gardez un oeil sur le terminal de VSCode également.
Ajout d’un fichier HTML
Nous allons améliorer notre code avec une page HTML à servir
Note : Pour éviter de redémarrer à la main à chaque fois qu’il y a une mise à jour du code, je vous suggère d’installer nodemon, un démon NodeJS, qui va redémarrer le serveur automatiquement à chaque enregistrement de fichier.
npm install --save-dev nodemon // installe en tant que dépendance de développement
// redémarrer le serveur
nodemon ./index.js localhost 3000
Intégration de socket.io
Maintenant on va allez voir les choses intéressantes, l’intégration de socket !
Il nous faut agir sur deux fronts, sur le serveur et sur le client. Il y a donc deux partie à la librairie socket.io. (nous sommes toujours en architecture client/serveur)
Socket.io côté serveur
npm install socket.io
et éditons le fichier index.js
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
// début de code de gestion du socket
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
// fin de code de gestion du socket
server.listen(3000, () => {
console.log('listening on *:3000');
});
Notez qu’on crée le serveur de socket en lui passant dans le constructeur le server NodeJS. « connection » est l’événement qui se déclenche lorsque la page dans le front end se charge pour la première fois et qu’un message donc est envoyé au serveur.
Socket.io côté client
Ajoutez le snippet dans le fichier HTML avant la fermeture de body
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
ça y est notre application web est équipée!
Maintenant ouvrez la page a port 3000, votre terminal nodeJS va afficher ‘a user connected’. Ce qui se passe c’est que lorsque la page est loadée, la librairie socket.io va envoyer un signal vers le serveur, qui intercepte le message. Si vous bne voyez rien, rafraichissez la page.
Construction de l’application de messagerie instantanée
Maintenant côté client, écrivons le code JS pour émettre les messages entrés au clavier, dans le formulaire:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
var form = document.getElementById('form');
var input = document.getElementById('input');
form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
socket.emit('chat message', input.value);
input.value = '';
}
});
</script>
et côté serveur on va afficher le message, ajoutez le snippet suivant :
Tapez les messages dans le formulaire, observez les logs côté serveur.
Le broadcasting côté serveur
Intéressons nous maintenant sur comment le serveur va émettre un message pour tous les client connectés, à la manière d’une station radio, d’où le terme ‘broadcasting’. Il faut utiliser la méthode emit() de l’objet io. Modifiez le code :
Il ya plusieurs façons de débugger NodeJS avec VSCode, le plus simple (mais peut être le plus ennuyant) est d’utiliser l’auto Attach, dès qu’un process NodeJS est démarré, VSCode se met en écoute. On va utiliser cette méthode. Pour plus d’information sur les autres méthodes allez sur cette page.
Utiliser les dev tools pour visualiser les communication via le socket
Vous pouvez voir les connexion socket comme vous pouviez le faire avec les requêtes Ajax. Dans les devtools, allez dans l’onglet Réseau, cliquez sur WS dans les filtres (à côté de XHR, Images etc.
Dans l’onglet Réponse, vous pouvez voir en fait les allées et venues des messages.
Ce que tous les développeurs web connaissent, ce sont les événements du DOM, les clics de souris, les survol, les chargements de page. Soit la page HTML suivante, un formulaire avec une div cachée qui se révèle dès que le formulaire change
let email = document.querySelector('#email')
let name = document.querySelector('#name')
let formulaire = document.querySelector('#formulaire')
let popup = document.querySelector('#popup')
formulaire.addEventListener('change', (e) => {
console.log('form has changed')
popup.style.display = 'block'
})
Mais il est aussi possible de lancer des événement depuis n’importe quel objet en Javascript, et ceci va nous permettre de coder notre application avec des événements, permettant une grande souplesse et découplage.
Par exemple, imaginez un formulaire avec login et mot de passe, di les deux champs sont validés, nous voulion faire apparaitre une popup.
let email = document.querySelector('#email')
let name = document.querySelector('#name')
let formulaire = document.querySelector('#formulaire')
let popup = document.querySelector('#popup')
popup.addEventListener('formEvent', (e) => {
popup.style.display = 'block'
})
//create the CustomEvent
const formEvent = new CustomEvent('formEvent', { detail: "les détails" })
formulaire.addEventListener('change', (e) => {
console.log('form has changed')
popup.dispatchEvent(formEvent)
// popup.style.display = 'block'
})
Il faut mettre bubble à true pour que l’événement se propage
let email = document.querySelector('#email')
let name = document.querySelector('#name')
let formulaire = document.querySelector('#formulaire')
let popup = document.querySelector('#popup')
popup.addEventListener('formEvent', (e) => {
popup.style.display = 'block'
})
//create the CustomEvent
const formEvent = new CustomEvent('formEvent', { detail: "les détails",bubbles:true })
formulaire.addEventListener('change', (e) => {
console.log('form has changed')
popup.dispatchEvent(formEvent)
// popup.style.display = 'block'
})
function test() {
console.log('this in a function', this);
}
const test2 = () => {
console.log('this in arrow function', this);
}
test2() // objet window
test() // objet Window
Comme on est dnas l’espace global (Window) le mot clé this représente Window. En effet les deux fonction sont définie dans l’espace de nom global et non dans un objet.
Le mot clé this dans l’espace de nom global
dans une fonction, la valeur de this dépend de comment la fonction est appelée. Considérez this comme un paramètres caché de la fonction. this est l’objet dans lequel la fonction est appelée.
Le cas des fonctions flèches
function test() {
console.log('this in a function', this);
}
const test2 = () => {
console.log('this in arrow function', this);
}
// test2() // undefined
// test() // objet Window
const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };
obj1.test = test
obj2.test2 = test2
console.log(obj1.test()) // this est l'objet obj1
console.log('arrow ', obj2.test2()) // this est l'objet Window
Dans les fonctions flèche, le this représente toujours l’objet global Window, alors que dans les fonctions classiques this représente l’objet dans lequel la fonction est définie.
Le cas du strict-mode
"use strict";
function show() {
console.log(this);
}
show(); // undefined
This dans un event listener
Ici c’est plus courant, vous avez déjà vu avec Jquery le $this, en Javascript pur c’est pareil avec this
Dans ce tutoriel nous allons voir comment simplement backtester une strétégie avec Tradingview, cet outil existe en gratuit et fait dans la verison gratuites énormément de chose.
On va écrire le script en Pinescript, et on va exécuter le backtest.
Ceci n’est pas un conseil financier.
strategy("Moving average Cross")
// Pinescript c'est L4G (langage de 4ème génération)
ema20 = ema(close,20)
ema50 = ema(close,50)
// on définit quand est ce qu'on long ou short
long = ema20 > ema50
short = ema20 < ema50
//ouverture du trade
strategy.entry("long", strategy.long,1.0,when=long)
strategy.entry("short", strategy.short,1.0,when=short)
// fermeture du trade
strategy.close("long",when=short)
strategy.close("short",when=long)
Cliquez sur « Update on chart »
Un fois que vous avez fait le script il faut clicker sur « Strategy tester », à côté de « Pine Editor », dans le sous menu, Overview vous pouvez voir la courbe de PNL
//@version=4
strategy("Moving average Cross")
ema20 = ema(close,20)
ema50 = ema(close,50)
long = ema20 > ema50
short = ema20 < ema50
start = timestamp(2021,04,01,0,0)
end = timestamp(2024,04,01,0,0)
if time >= start and time <= end
strategy.entry("long", strategy.long,1.0,when=long)
strategy.entry("short", strategy.short,1.0,when=short)
strategy.close("long",when=short)
strategy.close("short",when=long)
il faut mettre @version=4 sinon la condition if ne marche pas
Ensuite cliquez sur « Update on chart » pour que ça marche
Affichage des deux moyennes mobiles
//@version=4
strategy("Moving average Cross")
ema20 = ema(close,20)
ema50 = ema(close,50)
long = ema20 > ema50
short = ema20 < ema50
plot(ema50, title="ma50", color=#ffc1cc, linewidth=3)
plot(ema20, title="ma20", color=#00ffaa, linewidth=2)
start = timestamp(2021,04,01,0,0)
end = timestamp(2024,04,01,0,0)
if time >= start and time <= end
strategy.entry("long", strategy.long,1.0,when=long)
strategy.entry("short", strategy.short,1.0,when=short)
strategy.close("long",when=short)
strategy.close("short",when=long)
//Version avec Overlay sur la courbe des prix
il suffit de modifier la première ligne de code
strategy("Moving average Cross",overlay=true)
Ensuite cliquez sur « Update on chart » pour que mettre à jour le graphe, les deux moyennes mobiles sont dans le bas de l’écran séparés du graphique des prix. Ajoutez la propriété overlay=true pour superposer les deux graphique, auparavant supprimez le graphique du bas avec les deux moyennes mobiles.
Retarder l’entrée en position à la 10ème bougie en plus de la condition des moyennes mobiles
On fait ceci pour éviter que le croisement des moyennes mobiles ne soit que éphémères.
//@version=4
strategy("Moving average Cross",overlay=true)
ema20 = ema(close,20)
ema50 = ema(close,50)
long = ema20 > ema50
short = ema20 < ema50
//on attend la consolidation pour passer à l'action pour éviter de se faire stopper
longcondition = long and long[10] and not long[11]
shortcondition = short and short[10] and not short[11]
plot(ema50, title="ma50", color=#ffc1cc, linewidth=3)
plot(ema20, title="ma20", color=#00ffaa, linewidth=2)
start = timestamp(2021,04,01,0,0)
end = timestamp(2024,04,01,0,0)
if time >= start and time <= end
strategy.entry("long", strategy.long,1.0,when=longcondition)
strategy.entry("short", strategy.short,1.0,when=shortcondition)
strategy.close("long",when=shortcondition)
strategy.close("short",when=longcondition)
On a pris moins de trade mais le PNL est moins intéressant, mais vous voyez ici l’idée, on joue sur les potard afin d’améliorer le PNL. Une fois que vous avez des résultats intéressants, vous pouvez appliquer pour le futur dans votre stratégie de quant.
Après le réglage
Avertissement sur les limites du backtesting
Le backtesting n’est pas trivial, et ce qui est donnée par Tradingview peut ne pas être juste dans la réalité. Regardez cette vidéo
Le quant marche mieux dans le low time frame intraday avec des bougies d’un quart d’heure. je ne suis pas spécialiste et j’ai fait cet article à des fin didactique, je n’ai pas fait de robot de trading.
Non je ne parle pas de l’événement « click » ou « onclick », mais carrément de créer un événement souris. En javascript nous disposons de MouseEvent, qui ne se limite pas au seul clic gauche ou droit, mais tient compte aussi des déplacements de la souris.
var clickEvent = new MouseEvent('click', {
bubbles: true,
cancellable: true,
clientX: 32,
clientY: 32,
})
Voici le la documentation officielle de MouseEvent. Cependant je dois aussi vous dire qu’il y a un autre événement appelé PointerEvent. Cet événement est plus générique, car il peut gérer les événement touch, multi contact, alors que MouseEvent ne peut pas. Mais dans cet article nous allons nous concentrer sur MouseEvent.
function simulateClick() {
let titre = document.querySelector('h1')
let clickEvent = new MouseEvent('click', {
bubbles: true,
cancellable: true,
/* offsetX: 20,
offsetY: 20,*/
})
console.log('dispatch')
titre.dispatchEvent(clickEvent)
console.log('clicked')
}
let h2 = document.querySelector('h1').addEventListener('click', function (e) {
alert('toto')
})
setTimeout(simulateClick, 300)
La fonction simulateClick() va sélectionner l’élément H1 et la mettre dans la variable titre, construit un objet Event (MouseEvent pour être plus précis, MouseEvent héritant de Event), ensuite et c’est là qu’il faut être attentif, c’est titre qui va émettre (dispatch) l’événement clickEvent.
Dans le programme principal, h2 qui représente le même élément que titre reçoit une simulation de click et donc une alert() va faire apparaitre une popup. au bout de 300 millisecondes.
Liens en rapport avec l’article:
/////////////////////// DOM onunload //////////////////// https://stackoverflow.com/questions/11177233/javascript-event-that-runs-before-page-changes https://stackoverflow.com/questions/446892/how-to-find-event-listeners-on-a-dom-node-in-javascript-or-in-debugging https://stackoverflow.com/questions/4386300/javascript-dom-how-to-remove-all-event-listeners-of-a-dom-object/64484951#64484951
Un module est un fichier tout simplement rien de plus. On parle de module en javascript moderne, en effet ce concept n’existait pas avant ES6. Les modules existent en NodeJs également. Mais dans cet article je ne vais parler que des modules côté client.
Avant l’existence des modules, on ne pouvait pas importer un fichier Javascript dans un autre fichier Javascript comme on peut le faire en PHP.
Ici on ne va parler que des modules front end, dont la syntaxe est différente des modules dans NodeJS, dans ce dernier il existe au moins deux façon de faire, avec require() (commonJs) et import (AMD).
Comment on faisait avant pour importer un script Javascript?
On se servait de la balise script our importer les fichiers, index.js ne pouvait pas importer helper.js. La conséquence est que dans un fichier HTML on pouvait avoir facilement plus d’une dizaine d’import de fichier javascript. Cela pouvait avoir un impoact sur la rapidité du site.
Et vinrent les modules Javascript
Dès qu’il y a un import de modules, on observe au minimum deux fichiers. Soient deux fichiers, un principal.js, et un helper.js
//index.html
<script type="module">
import {sayHi} from './helper.js';
sayHi('John');
</script>
// helper.js
export function sayHi(name){
console.log('Hello ' + name)
}
On peut importer une fonction à condition qu’elle ait été exportée depuis le fichier helper.js. Dans la balise script on doit ajouter l’attribut type= »module » pour que cela marche.
Les caractéristiques de modules
Les modules utilisent le mode strict
Dans un code Javascript vous utilisez le mode strict pour forcer une plus grande rigueur dans la programmation
Par exemple dans un fichier HTML
<script>
a = 5 // autorisé pas d'erreur dans la console
</script>
Par contre
<script>
"use strict"
a = 5 // ReferenceError: a is not defined
</script>
de même dans un module
<script type="module">
a = 5 // ReferenceError: a is not defined bien qu'on n'ait pas eu à mettre use strict
</script>
Le scope des variables
Chaque module a son scope pour ses variables (je parle des variable globales du module, pas les variable locales des fonctions), les modules ne communiquenet donc pas leur variables, autrement dit, un module ne peut utiliser une variable globales d’un autre module.
// user.js
let user = "Jules"
// main.js
console.log(user) //
//index.html
<script type="module" src="user.js"></script>
<script type="module" src="hello.js"></script>
la console va afficher "SyntaxError: The requested module './lib.js' does not provide an export named 'user'"
//on modifie dans user.js
export let user = "Jules" // correct
//Pour illustrer directement dans une page HTML
<script type="module">
export let user = "Jules"
</script>
<script type="module">
console.log(user) // Erreur,et on ne peut faire import du module puisqu'il est inline, la seule façon urait été de faire window.user = "Jules"
</script>
Evaluation une seule fois du module à l’import
//index.html
<script type="module">
window.test = 0
</script>
<script type="module">
import { val } from './util.js'
</script>
<script type="module">
import { val } from './util.js'
console.log(val)
</script>
// util.js
window.test++
export let val = window.test
bien que l’on ait importé deux fois le module util.js, le code va afficher 1 et non 2
Prenons un autre exemple, qui va montrer que cet aspect est en fait pratique, permet aux différents scripts de se « partager » une variable
<script type="module">
alert(typeof button); // ce module est defer, il se télécharge immédiatement, mais il attend que le HTML finisse de se télécharger avant de s'exécuter.
</script>
<script>
alert(typeof button); // s'exécute immédiatement après le téléchargement, avant que le HTML du bouton ne vienne
</script>
<button id="button">Button</button>
Toujours préciser le chemin,
Même si le script est adjacent à votre page HTML, il faut préfixer avec un point slash
import {compteur} from 'util.js'; // dans un navigateur ceci n'est pas autorisé,TypeError: Failed to resolve module specifier "util.js". Relative references must start with either "/", "./", or "../".
import {compteur} from './util.js';
scripts externes et CORS
L’inclusion de script externe en tant que module doit se faire avec précaution dans le cas des modules. Pour les scripts externes de même origine que la page HTML, pas de soucis, mais si le script vient d’un autre nom de domaine, alors le serveur d’origine
<script type="module" src="https://site.com/script.js"></script>
il faut que site.com ait activé le CORS.
async et les modules
Le mot clé async permet de télécharger en parallèle un script javascript externe, mais ne s’utilise pas pour les script inline (à même la page HTML). dans le cas des modules, le mot clé async s’applique aussi aux Javascript inline.
<script async type="module">
import {counter} from './utils.js';
counter.count();
</script>
Ces attributs lorsqu’il sont utilisés sur une page HTML on tous un point commun : ils permettent de télécharger de façon asynchrone les fichiers liés depuis la page web, dans le but d’accélérer le téléchargement de la page et son exécution.
Async et Defer s’appliquent à la balise <script> uniquement
Comment utiliser ces deux attribut dans un script ? voici un exemple
<script src="init.js" defer></script>
ou
<script src="init.js" async></script>
Quelle est la différence entre async et defer? Regardez les deux schémas tirés de ce site,
async ne vas pas attendre la fin du téléchargement de la page HTML pour s’éxécuter, alors sur defer va attendre la fin du téléchargement de la page HTML (le parsing plus exactement).defer va être utile si vous avez besoin que tous les éléments du DOM soient mis en place.
preload permet de télécharger de façon asynchrone les ressources indiquée (css, javascript), mais il ne sont pas exécutés. Ils seront exécutés par le navigateur en cas de nécessité, ce qui est une bonne forme d’optimisation. Pour en savoir plus sur les détails techniques, cette page de la documentation officielle sur MDN.
Cet attribut a pour but de prétélécharger une page (même si on ne va pas la visiter) pour que lorsqu’on clique sur le lien, on n’ai pas à la télécharger. Il faut bien sûr s’assurer que c’est une page souvent visitée. La page prétéléchargée sera dans le cache prefetch.
L’image ci-dessus explique le fonctionnement (source : lien de la source).
The push refers to repository [docker.io/yvonhuynh/hello2]
An image does not exist locally with the tag: yvonhuynh/hello2
Si vous venez de commencer récemment à suivre un tutoriel Docker et que vous avez ce message, alors il y a peut être deux raisons, la seconde raison est plus probable.
Le contexte :
vous avez construit une image docker et vous aimeriez la pousser ver le hub de docker, mais vous rencontrez ce message lorsque vous poussez votre image soit depuis le Docker Desktop, soit depuis la ligne de commande.
Le dockerfile:
FROM node:alpine
COPY . /app
WORKDIR /app
CMD node app.js
Le projet javascript:
console.log('bonjour version 2')
Première raison possible :
Vos identifiants de connexion ne son tpas les bon
Cette raison est à titre préventif, il est fort à parier que ce n’est pas le cas.
docker logout
docker login
// renseignez vos identifiants.
Seconde raison possible:
Vous n’avez pas donné un tag à votre image
Vous avez buildé une image avec la commande:
docker build -t hello2
docker tag nom_image NOM_DOCKERHUB/nom_image
docker tag hello2 yvonhuynh/hello2
docker push yvonhuynh/hello2
Le nom de l’image s’appelle hello2 dans le hub docker.
yvonhuynh est le login de votre registry docker sur le site docker.com (dans notre cas mais il existe d’autres registry). un registry est comme un repository git.
lorsque vous faites des requêtes sur les éléments d’une page HTML et en faisant un affichage des éléments que vous avez obtenus, parfois vous avez des nodelist et parfois vous avez des Element, cela peut prêter à confusion parce que à première vue ce sont deux choses qui sont similaires, mais alors si elles sont similaires pourquoi elle portent deux types différents?
Node (Nœuds) dans le DOM
Dans le DOM, tout est un nœud. Un nœud peut être un élément, un attribut, un texte, un commentaire, un document, ou tout autre type d’objet DOM. Les nœuds sont organisés dans une structure arborescente, avec le nœud de document en haut et tous les autres nœuds en découlant.
Les nœuds ont des propriétés et des méthodes qui vous permettent de les manipuler ainsi que leurs nœuds enfants. Par exemple, vous pouvez utiliser la méthode appendChild() pour ajouter un nœud enfant à un nœud existant.
Éléments dans le DOM
Les éléments sont un type spécifique de nœud qui représente un élément HTML ou XML. Les éléments ont toutes les propriétés et méthodes d’un nœud, mais ils ont également des propriétés et des méthodes supplémentaires qui leur sont propres.
Par exemple, les éléments ont une propriété tagName qui spécifie le nom de l’élément, tel que « div » ou « span ». Les éléments ont également des attributs, qui peuvent être accédés en utilisant la méthode getAttribute() ou simplement en accédant à l’attribut comme une propriété de l’élément.
Il existe 12 types de noeuds
Element est un type de noeud, il y a aussi les noeuds TEXT, COMMENT, etc. Mais le plus familier pour nous est le type Element, les éléments de la page HTML.
Quand obtient l’un ou l’autre?
Lorsque vous faite une requêtes qui peut retourner plusieurs item, vous obtenex un NodeList (ce n’est pas un tableau !)
<div class="container">
<ul id="liste">
<li id="un">Un</li>
<li id="deux">Deux</li>
<li id="trois">Trois</li>
</ul>
</div>
let el = document.getElementById('un')
console.log(el) // retourne un Element
let nodelist = document.querySelectorAll('li')
console.log(nodelist) // retourne un nodeList
Dans l’exemple ci-dessus, même si le second exemple retourne un NodeList, les items de cette nodelist sont des Elements ! Vous pouvez le vérifier avec instanceof
Mais alors pourquoi dans ce cas on ne fait pas un objet ElementList? c’est un choix des ingéieurs qui ont fait Javascript.
Par contre HTML5 définit un objet HTMLCollection, qui est un objet qui ne contient que des Element, qui exclut tous les autres types de noeuds. Vous pouvez voir HTMLCollection à l’oeuvre avec l’exemple suivant:
let el = document.getElementById('liste')
En pratique vous n’avez pas à vous soucier de ces subtiles différences.
Cela fait pas mal de temps que je voulais m’investir dans un projet blockchain, à défaut de blockchain publique, je vais travailler sur une blockchain privée, et c’est sur Hyperledger.
Le type de projet de tokenization immobilière, thème très en vogue actuellement. Le but est de permettre une plus grande liquidité dans l’immobilier et de dépoussiérer les pratiques en vigueur.
RealtyKey.io est la plateforme web2 pour aborder le web3.
Principe de RealtyKey
Le principe est un principe d’investissement. Jusque là rien de différent, là où ça commence à se différencier de la finance traditionnelle, c’est que vous achetez un certificat d’investissement, appelé NFT et ce après avoir créé un compte (vous obtenez un AccountKey), vous détenez un NFT InvestKey prouvant que vous êtes inscrit . Ce dernier NFT vous permet de minter deux autres types de NFT, les Incomekey qui vous permettent de toucher un loyer du bien dans lequel vous avez investi, et les RealtyKey qui vous permettent d’habiter quelques temps dans un bien dans lequel vous avez investi.
La stack technique
La blockchain Hyperledger est contenue dans un Kubernetes, un orchestrateur de conteneurs Dockers. Le langage de développement de la blockchain, celui utilisé pour écrire les smart contracts appelé chaincode dans Hyperledger, est le langage Go, assez facile à appréhender.
Hyperledger expose un webservice directement consommable via Postman par exemple.
C’est assez différent de ce que je connais sur les blockchains publiques, notamment Ethereum et autres EVM compatibles. Le langage pour faire les smart contracts pour les chaine EVM est Solidity , que certains disent assez proche de Javascript, ce que personnellement je ne trouve pas, c’est assez unique.
Les différences entre une blockchain privée et une blockchain publique
Le choix d’une blockchain privée est motivée par les raison suivantes (non exhaustives)
pas de notion de consensus
milieu confiné à priori non sensible aux hacks
grand TPS
beaucoup plus sécurisée
Pourquoi utiliser la blockchain pour investir de façon fractionnée dans l’immobilier?
La blockchain permet de tout tracer sans pouvoir de falsification. Le fait de tokéniser rend l’actif plus liquide, et améliore la facilité de trouver une contrepartie quand on veut vendre.
Meilleure liquidité
Le ticket d’entrée bas permet à tout le monde de participer à la possession d’un bien. Vous n’avez pas à passer les étapes du notaire, DPE, etc. Tout est fait, vous n’avez qu’à entrer dans un investissement après avoir obtenu votre account key. L’opération ne prend que 15 minutes.
Meilleure contrepartie
L’apport de liquidités et l’ouverture à un marché financier cryptonatif plus vaste permettra une plus grande participation d’acteurs (idéalement particuliers comme institutionnels), concrètement si vous ne voulez plus investir dans un bien, où que vous voulez arbitrer vers un autre bien, et que vous voulez vendre vos parts, vous trouverez plus facilement un acheteur pour vos parts.
Ceci est à mettre en opposition avec un produit comme la SCPI, où il est notoire que les conditions de sortie sont plus délicates et de loin (clause de sortie, illiquidité du produit).
J’ai rencontré les plus grandes difficultés lorsque j’ai dû concaténer les colonnes du fichier texte. En effet dans une requêtes SQL de type INSERT, il y les valeurs à entourer d’apostrophe dans le fichier de sortie, donc il faut échapper le caractère apostrophe, et ce n’est pas un simple backslash, car le backslash doit être échappé par une apostrophe pour être reconnu comme un backslash d’échappement !
Contexte : je suis sous MacOS en architecture Intel 64bit (processeur Core i5)
Selenium vous permet programmatiquement d’émuler un navigateur (ici ce sera Chrome), et de télécharge une page et de l’analyser. Pourquoi est ce que c’estintéressant? Pour les test d’interface d’une part, puis d’autre part si vous voulez scraper une page très javascript, où les éléments sont rendus en JS donc non récupérables par un scrap avec BeautifulSoup, Selenium le peut.
Il est juste plus lent que BeautifulSoup, en effet il se repose sur le navigateur Chrome (notre cas ici mais ça peut être n’importe quel navigateur) qui fait le rendu, alors que BeautifulSoup ne fait pas le rendu.
Pré-requis :
connaissez votre version de navigateur Chrome, en allant dans les 3 petits point puis Aide puis A Propos de Google Chrome
Déterminez l’architecture de votre plateforme
Ensuite allez sur le site de Chromium pour télécharger le chromedriver à mettre dans le même répertoire que votre script, le driver permet à Selenium de contrôler Chrome, c’est dépendant de l’OS et du microprocesseur. Il faut suivre le lien pour les dernières versions de Chrome Vous trouverez aussi les zip de Chrome for testing, que Selenium va lancer. chromedriver et Chrome for Testing doivent être téléchargés ensemble.
Installer la librairie Selenium pip install selenium
Script minimal de Selenium pour scraper une page
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
browser = webdriver.Chrome() #mac https://stackoverflow.com/questions/76928765/attributeerror-str-object-has-no-attribute-capabilities-in-selenium
#driver = webdriver.Chrome('./chromedriver'). #ne marche pas sur Mac
browser.get("https://www.python.org")
print(browser.title)
Cette commande permet de charger des données dans une table de votre base de données à une très grande de vitesse. J’ai pu par exemple insérer 500000 lignes en seulement 7 secondes. C’est quelque chose à considérer si vous avez de grosses bases à reproduire dans un environnement. En effet, par le passé, j’ai travaillé dans une entreprise où il fallait attendre 6h pour mettre en place la base de données, je pense que avec cette méthode on pourrait très bien ramener à moins de 10 minutes. Attention, le chargement est très rapide pour une table donnée, je ne tiens pas compte du temps de passage entre une table et une autre, mais normalement il n’y a pas de problème.
La méthode la plus souvent utilisée pour insérer un fichier dans une table, et de faire un fichier constitué de clause insert, cette méthode n’est pas très rapide en effet si vous avez plusieurs lignes insert mais c’est plusieurs requêtes qui sont faites cependant on peut optimiser en faisant un insert multiligne, mais même ça ça ralentit le chargement des données. En effet le fait d’exécuter une requête SQL va faire intervenir le moteur de base de données, qui doit lire la requête SQL l’interpréter l’exécuter et mettre en mémoire les choses.
Avec cette méthode, en outre passe l’exécution de requête SQL, en effet par exemple lorsque en charge un fichier CSV, il n’y a pas de requête SQL qui est faite, on injecte les données simplement colonne par colonne, ligne par ligne. Il n’y a donc pas d’exécution de code SQL, c’est une insertion brute, c’est pour ça que c’est aussi rapide.
Dans vos bases de données de développement, par exemple e-commerce, vous pouvez vous permettre d’utiliser une méthode traditionnelle, mais si vous êtes amené à travailler avec de grosses bases de données, comme un Big Data, analyse des données, vous avez de très grosses bases de données, à reconstituer dans la base de données. Cette méthode est donc très avantageuse.
Le problème avec cette fonction
Le problème avec cette fonction c’est qu’il est assez difficile de le paramétrer, en particulier avec mysql8. Le problème est encore plus ardu lorsque vous utilisez PHPmyadmin pour faire l’insertion de données. En effet, on intercalant entre le fichier et la base de données un logiciel écrit en PHP donc pas forcément très performant, vous augmentez les chances que cela ne marche pas. Je vous recommande donc de faire l’insertion depuis la ligne de commande. Même malgré ça nous allons rencontrer quelques difficultés.
Nous allons prendre un exemple simple, avec un petit fichier test.csv de quelques lignes, nous allons surtout nous concentrer sur la partie amont de l’insertion.
Nous allons disposer d’une table dont voici le code
CREATE TABLE `test` (
`id` int NOT NULL,
`nom` varchar(50) NOT NULL,
`prenom` varchar(50) NOT NULL,
`email` varchar(150) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Première tentative d’insertion dans PHPMyAdmin
Pour information la documentation officielle traitant de cette fonction se trouve sur cette page. La doc officielle dit aussi que MySQL doit avoir les privilèges sur les fichier à importer (logique), par exemple il doit avoir les droit de lecture sur le fichier test.csv.
LOAD DATA LOCAL INFILE 'E:\OneDrive\formapedia_cours\coursSQL\load infile\test.csv' INTO TABLE test
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(id, nom,prenom,email);
Ceci se solde par une erreur « #2068 - LOAD DATA LOCAL INFILE is forbidden, check related settings like mysqli.allow_local_infile|mysqli.local_infile_directory or PDO::MYSQL_ATTR_LOCAL_INFILE|PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY« . Ce qui est embêtant car je vois PDO donc j’imagine que ce doit être un réglage PHP dans PHPMyAdmin, il va falloir bidouiller le fichier de configuration. Je vois aussi qu’il y a un réglage dans le fichier de configuration de MySQL. Recherches infructueuses. Ce que je vois est qu’il faut mettre une variable de configuration dans my.ini (Windows) ou my.cnf (Linux)
[mysql]
local-infile=1
[mysqld]
...
local_infile=1 << parfois je vois local-infile=1 (avec le trait d'union)
[mysqldump]
quick
max_allowed_packet=512M
En redémarrant le serveur, je n’ai pas plus de succès…
Je tente de passer par MySQL en ligne de commande
En fait je fais ça, car je sais que PhpmyAdmin introduit une couche de configuration rendant la tâche plus délicate. Je passe donc par la ligne de commande qui est plus simple. En se connectant en ligne, n’oubliez pas de sélectionner la base de donnée avec use.
En collant le texte ci-dessous: Attention \r\n dans le système Windows mais \n tout court pour Linux
LOAD DATA LOCAL INFILE 'E:\OneDrive\formapedia_cours\coursSQL\load infile\test.csv' INTO TABLE test
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(id, nom,prenom,email);
J’ai a réponse suivante:
ERROR 2068 (HY000): LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.
C’est donc une question de restriction de lecture de fichier, mais je suis sous Windows, je ne m’inquiète pas trop (Linux est plus subtile), j’essais néanmoins de placer le fichier csv dans le répertoire où se trouve la base de données (dans le répertoire d’installation de MySQL, chaque base de données correspond à un fichier binaire, dans un répertoire de même nom (dans le cas de InnoDB). Mais j’ai toujours le même problème.
CTRL + SHIFT + P puis Python: Create Environment et sélectionnez la commande.
Choisissez l’interpréteur
Ensuite ça prend un peu de temps pour créer l’espace virtuel, isolé de développement Python.
Pour s’assurer de la version de l’interpréteur Python, dans la palette de commande (CTRL + SHIFT + P) puis Python: Select Interpreter
Maintenant vous êtes prêt pour commencer à coder en Python dans VSCode.
Créez un fichier hello.py,
print("hello")
Pour exécuter, appuyez sur le triangle en haut à droite de VSCode, liste déroulante choisir Debug Python File. Notez le point rouge qui est le point d’arrêt.
Debugger python sous VScode
Il suffit de mettre un point d’arrêt et de cliquer sur le symbole debug dans la barre latérale. Une autre méthode est d’utiliser le menu contextuel et démarrer le script.
C’est un plugin navigateur qui vous permet d’exécuter du code Javascript sur la page où vous vous trouvez. Vous connaissez les extensions de navigateur? Greasemonkey vous permet facilement de retrouver les mêmes capacités sans avoir à coder toute l’extension.
Installez Greasemonkey version 4 (sur Chrome c’est TamperMonkey).
Pour aller au plus simple, cliquez sur l’icône du singe, vérifiez qu’il est bien activé puis cliquez sur Nouveau Script
// ==UserScript==
// @name Anonyme Script 813510
// @version 1
// @grant none
// ==/UserScript==
Sion on veut de l'ajax (cross domain en plus !)
//@grant GM.xmlHttpRequest
Vous pouvez personnaliser les annotations, @name pour le nom du script, @version qui n’aura pas d’influence sur votre scripts, et surtout @grant est très important, si vous voulez par exemple faire une requêtes Ajax, par défaut vous ne pouvez pas. Je vous joins la page de documentation du plugin:
Récemment j’ai eu droit en voulant activer mon thème Astra, je me suis heurté à l’erreur suivante :
cURL error 60: SSL certificate problem: unable to get local issuer certificate
Ce n’est pas un problème du thème Astra
Ce n’est pas un problème de votre hébergeur
J’ai fait 2 aller retours vers le hébergeur 02Switch, qui est très bien, réactif, mais n’a pu me solutionner mon problème, se contentant de dire que chez eux tout va bien. Bien sûr je ne savais pas quel était le vrai problème, je sentais que c’était un problème du serveur du site, et pas de celui d’Astra, comme me le suggérait l’hébergeur.
La solution est ailleurs
Ce n’est seulement qu’après avoir vu la petite vidéo d’Astra montrant que (tout plugins désactivés, le problème persistait, en effet en allant sur Outil > Santé du site, il y avait une alerte d’erreur critique concernant REST API, en gros les appels vers d’autres serveurs échouaient à cause du certificat.
En googlant un peu plus sur Internet, j’ai trouvé la solution sur cette page :
Le problème était que le certificat de WordPress, le fichier ca-bundle.crt localisé dans wp-includes/certificates, datait de 2016…
La solution consistait à télécharger un certificat plus récent sur ce lien le fichier ca-cert.pem. Le soucis c’est que ce fichier ne nommait pas pareil, pas de panique il suffit juste de copier le contenu texte de ce fichier et de remplacer l’ancien contenu intégralement du fichier ca-bundle.crt et le tour est joué.
L’order book est le livre des ordres de bourse à cours limité, ce sont des ordres en attente d’exécution, à la différence des ordres market, que vous ne verrez pas car ils sont passés immédiatement.
Les données vous permettent de tracer la profondeur de marché, de voir la densité des ordres en fonction du cours d’exécution
Quotation en temps réel à différents timeframes
Cette fonctionnalité est primordiale pour tracer les cours des crypto, on a besoin en version OHLC, pour tracer les bougies et faire de l’analyse technique dessus.
VSCode est vraiment l’éditeur de code couteau suisse, son avantage est que s’il y a un langage même confidentiel, vous trouverez un plugin. Même s’il n’est pas le meilleur dans chaque catégorie, par exemple je trouve PHPStorm mieux pour le PHP, il est un très bon outil gratuit de surcroît.
Pour NodeJs, c’est un peu plus simple que pour Xdebug en PHP, il y ap lusieur façons de déclencher le débugger de NodeJS, on va voir l’auto déclenchement du débugger dès qu’un process node est en cours d’exécution.
Je suppose que vous ayez un fichier index.js, à exécuter via la commande shell, pour le lancer vous faites node index.js. Si vous ne l’avez pas fait vous pouvez démarrer un projet NodeJS.
Et là vous devrez avoir la barre de status orange, indiquant que le débug est actif.
Configuration de VSCode pour le debug automatique (Auto attach)
Pour activer l’auto attach, faites la combinaison de touche : SHIFT + CTRL + P, une boite de recherche va apparaitre, tapez « Toggle Auto Attach » pour trouver l’option et cliquez dessus.
Maintenant chaque fois que vous démarrez un process NodeJS, VSCode se met en mode debug.
packge.json est le fichier important sans lui vous ne pouvez pas publier de package.
Le fichier index.js est le point d’entrée de votre package.
Le nom du package doit être unique dans tout le repository NPM, cela a donné à l’affaire du npmgate
Dans la barre de recherche de NPM vous pouvez chercher par nom de package.
Créez le fichier index.js
On va faire simple un seul fichier:
let uniqueArr = [];
function removeArrayDuplicates(arr) {
// Accepts an array from which the duplicates
// will be removed
if (!Array.isArray(arr)) {
arr = [];
}
let theSet = new Set(arr);
arr.filter((num) => {
if (!uniqueArr.includes(num)) {
uniqueArr.push(num)
}
})
return uniqueArr;
}
/* code de test */
let myNums = [1, 2, 3, 1, 4, 1, 2, 5, 3, 4];
let uniqueNums = removeArrayDuplicates(myNums)
console.log(uniqueNums);
Pour cela inutile d’aller sur le site web de NPM ! vous pouvez tout faire en ligne dans votre terminal. Enlevez le code inutile d’application qui vient après la fonction.
npm login
// entrez vos identifiants
npm publish
j’ai eu un problème car le nom du paquet existe déjà, donc ce qu’on peut faire c’est de changer vers un nom qui n’existe pas encore
Si vous installez pour la première fois NodeJS voici la comamnde avec Homebrew (je vous recommande de la farie avec Homebrew, pour les upgrade plus tard, c’est plus facile)
brew install node
npm install create-react-app
npx create-react-app monApp
Mise à jour de NodeJS sur MacOS
Si vous avez déjà NodeJs d’installé, vérifiez que vous avez la dernière version, si vous ‘avez pas la dernière version, faites un upgrade
Vérifiez votre version de nodeJS sur votre poste, et regardez quelle est la dernière version de NodeJS, pour ma part j’éatis à 12, la dernière version étant 19 !
> node -v
> brew upgrade node
Upgrader NodeJS non installé avec Homebrew
L’ennui est que je n’avais pas installé nodeJs avec Br–Hombrew, donc il fallait désinstaller à la main ! heureusement j’ai trouvé un script shell de désinstallation
Puis en en voulant faire un symlink
brew link node
J’ai eu une erreur de ce type :
Error: Could not symlink include/node/common.gypi
Il faut changer le mode, c’est un problème de droit
sudo chown -R $(whoami) $(brew --prefix)/*
brew link --overwrite node
Je vous conseille d’utiliser Homebrew pour avoir des install plus clean, et pas seulement pour nodeJS.
Installer create-react-app avec NPM
npm install create-react-app
//création du projet
npm create-react-app myApp
cd to folder
//lancement du projet
npm start
Vous pouvez utiliser NPX à la place de NPM, la différence c’est que NPX ne télécharge pas le package, à la différence de NPM.
MacOS est un dérivé de FreeBSD, donc contient déjà un serveur apache, mais c’est tout.
MAMP est une solution de développement intégré comme WAMP, Laragon ou encore XAMP.
Les version nouvelles de PHP sortant, il faut se mettre à jour. Nous allons voir comment mettre à jour la version de PHP avec Homebrew.
Mettre à jour HomeBrew
Ici il s’agit d’avoir la dernière version de Homebrew Core. Parfois vous avez le message suivant
Warning: homebrew/core is shallow clone. To get complete history run:
git -C "$(brew --repo homebrew/core)" fetch --unshallow
Cela veut dire qu’il faut avoir tout le code source de Homebrew, il faut taper la commande suivante (ça prend pas mal de temps), mais si vous ne le faites pas et que vous voulez installer une nouvelle version de PHP (ou de tout autre logiciel, vous n’arriverez pas). Exécutez la commande Git, shallow veut dire creux, en fait pour sauver de l’espace, tout n’était pas téléchargé.
it -C "/chemin/vers/homebrew/core" fetch --unshallow
Si vous n’avez pas ce message ce n’est pas grave, vous êtes en bonne voie. Patientez un bon moment pendant que cette commande s’exécute.
Installer la nouvelle version de PHP
brew install php@8.1
Cela va télécharger PHP dans le répertoire /usr/local/Cellar/php@8.1/lib, et dans /usr/local/opt/php/php8.1 qui est en fait un raccourci vers le premier répertoire, une fois dans le répertoire PHP localisé, vous avez deux sous répertoires, /httpd et /php.
Allez dans Cellar/php/ copier le répertoire php8.1 nouvellement créé, vers MAMP dans Application/MAMP/bin/PHP
Si le dossier PHP que vous avez collé ne s’appelle pas php8.1, renommez le comme ça car cela va permettre à MAMP de la reconnaitre au redémarrage. Redémarrez MAMP et sélectionnez la nouvelle version de PHP, par défaut seules les deux dernières versions de PHP sont montrées dans la liste déroulante.
Copier le fichier libphp.so
Démarrez le serveur Apache, vous allez voir une erreur, car il manque encore une manipulation à faire, il faut le fichier libphp.so.
Ce fichier est à récupérer dans le répertoire usr/local/lib/http/modules et à mettre dans /MAMP/bin/php/php8.1/modules