IT

Hello (test)

Windows

Pour changer le PATH dans windows sans droit administrateur

  1. Start Menu -> Panneau de configuration -> Comptes utilisateur

  2. Modifier vos variables d’environment

  3. Path et rajouter le chemin en séprant avec un point virgule (si déjà des paths présents)

  4. fermer la session et la ré-ouvrir

Faire un print-screen

Pour faire un PrintScreen uniquement sur un écran, placer le curseur sur le bon écran et faire :

M-PrintScreen

Si un seul écran, alors pas besoin de presser la touche Alt.

Impression à l’échelle d’un pdf

../_images/ImpressionAlEchelle1.PNG ../_images/ImpressionAlEchelle2.PNG ../_images/ImpressionAlEchelle3.PNG

Pour effacer un répertoire sous dos

rmdir /s

MINGW32

Pour envoyer un message avec Outlook

start Outlook //c ipm.note //m "mailto:johndoe@domain.com^&subject=Hello"
start Outlook //c ipm.note //m
"mailto:johndoe@domain.com;paul.traveri@gmail.com^&cc=are@gmail.com^&subject=Hello^&body=aslfdsff%0A%0Ajsdfjklé%0Aasdfjé"

Le %0A est pour insérer un retour à la ligne

emacs

Insatallation

  1. Installer MiKTteX (développer…)

  2. Installer emacs

    1. Prendre la dernière version du site officiel (le .zip)

    2. Dézipper

    3. M-x package-install

    4. choisir auctex

    5. C-x C-f ~/.emacs (cela créera le .emacs au bon endroit)

    6. copier ses lignes préférées dans celui-ci

.emacs

Le nom de ce fichier n’a pas de préfixe, il a juste un suffixe (extension) qui est .emacs Il faut le copier dans home/yd

Pour éditer le .emacs ou le créer au bon emplacement

C-x-f ~/.emacs

Contenu du .emacs

(set-language-environment 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-language-environment 'utf-8)
(prefer-coding-system 'utf-8)

;; Pour envoyer les choses deletée à la poubelle
(setq delete-by-moving-to-trash t)

;; Changement de thème
(load-theme 'misterioso)

;; Langue par défaut et caractères accentués
 (setq current-language-environment "French")

;; Position et mise en forme de la fenêtre
(setq default-frame-alist'
	((top . 00)
	 (left . 00)
	 (width . 85)
	 (height . 48)))
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)

;; Répondre 'y' plutôt que 'yes'.
(defalias 'yes-or-no-p 'y-or-n-p)

;; Pour que le curseur ne clignote plus
 (blink-cursor-mode 0)
;; Langue par défaut et caractère accentués
 (setq current-language-environment "French")

;; coupe les lignes au 72 ieme caractère
 (add-hook 'text-mode-hook 'turn-on-auto-fill)
 (defun auto-fill-hook ()
 auto-fill-mode 1)
 (setq fill-column 72)

;pas de beeep
(setq visible-bell 't)

;pas de message au démarrage
(setq inhibit-startup-message t)

;; Recherche non case-sensitive
 (setq case-fold-search t)

;; Afficher la parenthèse correspondante
 (require 'paren)
 (show-paren-mode t)

;; affiche date & heure
(display-time)
(setq display-time-24hr-format t)

;; ----------------------------------------------------------------------
;; COMMANDE AucTex / LaTex
;; ----------------------------------------------------------------------


;; correction orthographique
(autoload 'ispell-word "ispell" "Check the spelling of word in buffer." 't)
(autoload 'ispell-region "ispell" "Check the spelling of region." 't)
(autoload 'ispell-buffer "ispell" "Check the spelling of buffer." t)
(global-set-key (read-kbd-macro "M-$") 'ispell-word)
(setq ispell-dictionary "francais"
      ispell-skip-sgml t)
(autoload 'flyspell-mode "flyspell" "On-the-fly spelling checking" t)
(setq flyspell-default-dictionary "francais")

;; appelle de flyspell par f7 et f8 ispell-buffer
(global-set-key [f7] 'flyspell-mode)
(global-set-key [f8] 'ispell-buffer)


;; Sauvegarde des fichiers récemment ouverts + création d'un raccourci
;(add-to-list 'load-path "~/.emacs.d/lisp/recent")
;(require 'recentf)
;(recentf-mode 1)
;(defun recentf-open-files-compl ()
;  (interactive)
;  (let* ((all-files recentf-list)
;	 (tocpl (mapcar (function 
;			 (lambda (x) (cons (file-name-nondirectory x) x))) all-files))
;	 (prompt (append '("File name: ") tocpl))
;	 (fname (completing-read (car prompt) (cdr prompt) nil nil)))
;    (find-file (cdr (assoc-ignore-representation fname tocpl)))))
 
;(global-set-key "\C-x\C-l" 'recentf-open-files-compl)
 
;(require 'ido)
;(ido-mode t)
 
;; -----------------------------------------------------
;; CORRECTEUR ISPELL 
;; -----------------------------------------------------
 
;: Dictionnaire francais
;(setq-default ispell-program-name "aspell")
;(setq ispell-dictionary-alist
;      (cons
;       '("fr_FR-lrg" "[A-Za-zÀÂÆÇÈÉÊËÎÏÔÙÛÜàâçèéêëîïôùûü]"
;	 "[^A-Za-zÀÂÆÇÈÉÊËÎÏÔÙÛÜàâçèéêëîïôùûü]" "[-']" t nil "~list"
;	 iso-8859-1)
;       ispell-dictionary-alist)) 
 
;; Empèche Ispell de vérifier le contenu de certaines commandes 
;(setq ispell-tex-skip-alists
;      (list
;       (append (car ispell-tex-skip-alists)
;               '(("\\\\cite"            ispell-tex-arg-end)
;                 ("\\\\nocite"          ispell-tex-arg-end)
;                 ("\\\\includegraphics" ispell-tex-arg-end)
;                 ("\\\\figScale"         ispell-tex-arg-end)
;                 ("\\\\author"          ispell-tex-arg-end)
;                 ("\\\\ref"             ispell-tex-arg-end)
;                 ("\\\\eqref"             ispell-tex-arg-end)
;                 ("\\\\label"           ispell-tex-arg-end)
;                 ))
;       (cadr ispell-tex-skip-alists)))
 
;; Empèche Ispell de vérifier le contenu des citation natbib
;(eval-after-load "ispell"
;  '(let ((list (car ispell-tex-skip-alists)))
;     (add-to-list 'list '("\\\\cite[tp]" ispell-tex-arg-end))
;     (setcar ispell-tex-skip-alists list)))
 
 
;; -----------------------------------------------------
;; COMMANDES AucTeX / LaTeX
;; -----------------------------------------------------
 
;; Choix des programmes de visualition selon le fichier de sortie
;(setq TeX-output-view-style (quote (("^dvi$" "^pstricks$\\|^pst-\\|^psfrag$" "dvips %d -o && start %f") ("^dvi$" "." "xdvi %dS %d") ("^pdf$" "." "xpdf %o") ("^html?$" "." "start %o"))))  
;(setq TeX-view-style (quote (("^epsf$" "start %f") ("." "xdvi %dS %d"))))
 
;; Pour voir les les équations compilées directes dans  emacs
;(load "preview-latex.el" nil t t)
 
;; Quelques commandes additionnelles du mode LaTeX
;(add-hook 'LaTeX-mode-hook
;  (function
;    (lambda ()
;      (add-to-list 'TeX-command-list
;             (list "PDFLaTeX" "pdflatex %s.tex"
;                   'TeX-run-command nil t))
;      (add-to-list 'TeX-command-list
;             (list "Acroread" "acroread %s.pdf"
;                  'TeX-run-command nil t))
;      (add-to-list 'TeX-command-list
;             (list "XPDF" "xpdf %s.pdf"
;                   'TeX-run-command nil t))
;      (add-to-list 'TeX-command-list
;             (list "DVIPS" "dvips -o %s.ps %s.dvi"
;                   'TeX-run-command nil t))
;      (add-to-list 'TeX-command-list
;            (list "Clean" "rm %s.log %s.aux %s.out %s.idx"
;                   'TeX-run-command nil t))
;      (add-to-list 'TeX-command-list
;             (list "KghostView" "kghostview %s.pdf"
;                   'TeX-run-command nil t))
;      (TeX-PDF-mode)
;      ;gestion de la table matière et autre...
;      (reftex-mode)
;      ;; Corrrection à la volée syntaxique
;     (flyspell-mode)
;      ;; dictionnaire évitant les erreurs d'accents
;      (ispell-change-dictionary "francais")
;)))

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages '(auctex)))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

Pour envoyer les choses deletée à la poubelle de windows

Cela permet de récupérer les fichiers ou répertoire effacés par mégarde.

(setq delete-by-moving-to-trash t)

Pour ne pas être embêté par l’affichage des accents

Je préfère encoder en UTF-8. Pour cela j’insère ce bloc de code dans le .emacs

(set-language-environment 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-language-environment 'utf-8)
(prefer-coding-system 'utf-8)

Si le défaut persiste, on peut essayer les méthodes suivantes pour enlever remettre les accents.

Méthode 1
  1. renommer le fichier en .txt

  2. rouvrir ce dernier avec Emacs

  3. copier tout le contenu

  4. couper dans un nouveau fichier .tex

  5. à la demande d’Emacs si demande il y’a, ne pas l’enregistrer en UTF8, mais taper tab et choisir latin1

Remarque : Dans un pdf, si les accents sont bien présents dans emacs et pas dans le pdf. Il faut alors faire le racourci clavier suivant~: C-x RET f codage RET et choisir latin-1.

Méthode 2
  1. M-x revert-buffer-with-coding-system
    
  2. choisir utf-8 ou latin-1

Méthode 3

Si des accents s’affichent dans TeXworks malgré tous les packages et l’encodage UTF-8 réglés correctement (cela m’est arrivé lors d’un copier-coller du contenu de Outlook dans emacs.)

  1. copier le contenu du fichier.tex dans un bloc note

  2. enregistrer sous encodage UTF-8

Cela devrait fonctionner.

Méthode 4

You can also mark the entire file with C-x h and then try M-x recode-region. It will ask you for Text was really in and But was interpreted as. For the first file in your question, it looks like it should be latin-1 and utf-8, and for the second example it should probably be the other way around, utf-8 and latin-1.

After you got it right, you can choose which coding system to save the file with using M-x set-buffer-file-coding-system (or C-x C-m f for short).

copier/coller sans toujours à répondre à la même question du coding

Pour pouvoir copier/coller depuis windows et pour pas que emacs demande à chaque fois le format du coding, insérer la ligne suivante dans fichier .emacs.

(setq selection-coding-system 'compound-text-with-extensions)

Pour que les fichiers effacés en mode dired aillent dans la Corbeille de Windows

Placer ce code dans le .emacs :

(setq delete-by-moving-to-trash t)

Raccourcis clavier

Ci-dessous quelques raccourcis utiles pour l’utilisation de Emacs et LaTeX. La plupart de ces raccourcis ont été trouvés à l’addresse suivante https://loquehumaine.wordpress.com/2010/04/01/mes-raccourcis-emacs/ Un grand Merci donc à cette personne.

Général

Raccourcis

Descriptions

F7

mode flyspell correcteur orthographique)

F8

appelle Ispell buffer

C-h a

propos

C-h k

recherche de ce que fait un raccourci

C-g g

annuler

C-u 5 -

répète 5 fois

C-u 5 BackSpace

efface les 5 derniers caractères

M-/

complétion avec les mots des buffers ouverts

M-x load-buffer

charger un .emacs

M-x xxx-mode

mode xxx (latex,html,python,…)

M-$

ispell sur le mot

M-!

exécuter une commande bash

C-u- M-!

insérer le résultat d’une commande bash

M-x

écrire des commandes en ligne de commande

M-x menu-bar-mode

pour afficher / enlever la barre d’outils

M-x cua-mode

copier-coller d’une autre applications

C-x C-c

quitte Emacs

C-z

minimise Emacs

C-x u

pour annuler (undo)

C-x C-s

enregistre le buffer courant

Pour se déplacer

Raccourcis

Descriptions

C-a

aller au début de la ligne

M-a

aller au début de la phrase

C-e

aller à la fin de la ligne

M-e

aller à la fin de la phrase

C-f

se déplacer au caractère suivant

M-f

se déplacer au mot suivant

C-b

se déplacer au caractère précédent

M-b

se déplacer au mot

C-p

se déplacer à ligne précédente

C-n

se déplacer à ligne suivante

C-v

écran suivant

M-v

écran précédent

C-M-v

écran suivant dans l’autre buffer

C-l

mettre la ligne active au milieu du buffer

C-x l chiffres

aller à la ligne chiffres

M-<

aller au début du buffer

M-S-<

aller à la fin du buffer

C-u 0 C-l

met la ligne courante en première ligne du buffer

Marques

Raccourcis

Descriptions

C-SPC

faire une marque (donc le début d une région/rectangle)

C-@

faire une marque (donc le début d une région/rectangle)

M-@

marquer le mot (C-u 4 M-@ marquer 4 mots)

C-x C-x

échanger le point et la marque

C-u C-SPC

revenir en arrière sur les marques

M-h

sélectionner le paragraphe

C-x h

sélectionner tout le buffer

Editer, couper, copier, coller

Raccourcis

Descriptions

C-d

tuer la prochaine lettre

M-d

tuer le prochain mot

BackSpace

tuer la lettre présédente

M-BackSpc

tuer le mot précédent

C-k

tuer la fin de la ligne

C-w

tuer la région

C-y

coller le dernier truc tué

M-y

revenir plus en arrière dans la liste des

trucs tués (après C-y donc)

C-t

échanger 2 lettres

M-t

échanger 2 mots

C-x C-t

échanger 2 lignes

C-x r r

copier le rectangle

C-x r k

tuer le rectangle

C-x r y

coller le rectangle

M-z x

tuer jusqu’au caractère x

M-u

uppercase

M-l

lowercase

M-c

capital

C-x C-u

uppercase de la région

C-x C-l

lowercase de la région

Rechercher et remplacer

Raccourcis

Descriptions

C-s

chercher

C-r

chercher en arrière

M-%

chercher / remplacer (! pour tous, C-q C-j

pour insérer un saut de ligne, haut bas pour

naviguer dans l’historique des trucs

recherchés)

C-M-s

chercer avec regexp en arrière

C-M-%

chercher / remplacer avec regexp

M-x replace-string

recherche / remplacer (permet de remplacer

par un mot commençant par un \ )

Fenêtres / buffers

Raccourcis

Descriptions

C-x 1

le buffer courant devient le seul buffer

C-x 2

splitter horizontalement

C-x 3

splitter verticalement

C-x 0

la fenêtre du buffer courant est fermé

C-x k

tuer le buffer

C-x droite/gauche

naviguer dans la liste des buffers

C-x o

passe l’autre fenêtre

C-x b

ouvrir parmi les buffers

C-x i

insérer un fichier

Mode Dired

Raccourcis

Descriptions

q

close the file

c

copy file

R

rename file

D

Delete file

+

create a new dir

z

compress / decompress

m

mark a file

u

unmark

U

unmark all marked

&m

mark by file name extension

%m

mark by pattern (regex)

g

refresh

x

applique les changements

^

go to parent dir

dired-do-copy

copier le répertoire ou fichier

Mode LaTeX

Raccourcis

Descriptions

C-c C-s

nouvelle section (défaut : section, sinon la

plus petite sous-section courante)

C-c C-e

nouvel environnement (défaut : itemize)

C-c C-j

nouvel \item

C-u C-c C-e

changer l’environnement

C-c C-f C-c

textsc

C-c C-f C-e

emph

C-c C-f C-i

textit

C-c C-f C-b

textbf

C-c C-c C-t

texttt

C-c C-f C-r

textrm

si entre & &

mathrm, …

C-c C-f C-d

enlever le textxx

C-u C-c C-f C-?

remplacer le textxx par text??

C-c ;

commente la région

C-c %

commente le paragraphe

Formatage

Raccourcis

Descriptions

C-M-\

formater la région

M-q

formater le paragraphe

C-c C-q C-e

formater l’environnement

C-c C-q C-s

formater la section

C-c .

marquer l’environnement

C-c *

marquer la section

C-M-a

début d’environnement

C-M-e

fin d’environnement

Pour supprimer les ^M en fin de ligne

Faire la séquence suivante :

M-< C-q C-M Enter C-q C-j Enter !

Explications :

  1. M-< on se place au début du document

  2. M-% on active le mode de remplacement de caractères

  3. C-q C-M on va remplacer les ^M

  4. C-q C-j on va y mettre à la place des retours à la ligne

  5. ! on applique ces modifications à toutes les occurences rencontrées dans le fichier

Débugger emacs

C-c apostrophe espace

Changer le thème (couleur de fond,…)

J’utilise le thème misterioso (il en existe bien sûr d’autres)

(load-theme 'misterioso)

à placer dans le .emacs

Compilation

Compilation avec XeLaTeX depuis emacs

J’utilise souvent cette méthode pour compiler une figure dessinée par psTricks qui produit directement un pdf.

  1. afficher le menu :

    M-x menu bar-mode
    
  2. Command -> TeXing Options -> Use XeTeX engine

ou simplement :

C-c-c tab et sélectionner xelatex

../_images/Capture1.PNG

LaTeX

Installation LaTex, Emacs et auxtex sous Linux

  1. télécharger la dernière version de tex-live sur le site officiel

    1. télécharger le .iso

    2. copier les dossiers sur le bureau

    3. écrire dans un terminal :

      perl install-tl
      
    4. I

    5. etc/environement, modifier le fichier pour que ça ressemble à ceci :

      PATH="/usr/local/texlive/2016/bin/i386-linux:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
      MANPATH="/usr/local/texlive/2016/texmf/doc/man"
      INFOPATH="/usr/local/texlive/2016/texmf/doc/info"
      

    Note

    changer si nécessaire 2016

  2. installer emacs avec le synaptique

  3. installer auxtec avec le synap

  4. copier .emacs dans yd

  5. pour que auxtex et emac communique entre eux, il faut rajouter ces lignes dans le .emacs (si pas déjà fait)~:

(require 'tex-site)
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
(setq reftex-plug-into-AUCTex t)
(global-font-lock-mode t)

Tout ceci est tirer du site https:\www.math.purdue.edu/~dvb/xdvi.html pour que le script pour la conversion des Figures PSTicks fonctionne, il faut rajouter (dans le script) -shell-escape après la commande latex. (ex. latex -shell-escape 1.tex)

Fichier modèle Document LaTeX

Warning

Essayer toujours de travailler en encodage utf8, en partant du modèle en utf8.

A compiler avec pdflatex. Comprenant titre, logo et table de matière.

\documentclass[a4paper, 11pt,titlepage]{article}
\usepackage[T1]{fontenc}
%\usepackage[latin1]{inputenc}
\usepackage[utf8]{inputenc} % utf8 sinon essayer avec latin1
\usepackage{longtable}
\usepackage{array}
\usepackage{colortbl}              % Pour l'utilisation des couleurs
                                   % dans les tableaux et pour que
                                   % definecolor fonctionne
\usepackage{placeins}              % permet d'utiliser la commande FloatBarrier

\usepackage[left=2.3cm, right=1.8cm, top=2cm]{geometry} % See
                                % geometry.pdf to learn the layout
                                % options. There are lots. 
\geometry{a4paper} % or letterpaper (US) or a5paper or....
%\usepackage[parfill]{parskip} % Activate to begin paragraphs with an
%empty line rather than an indent

\usepackage[pdftex]{graphicx}
\usepackage[pdftex,bookmarksopen=false,pdfauthor=ydu,colorlinks=false,pagebackref,plainpages=false]{hyperref}

\begin{document}

\begin{center}
%pour mettre un titre  
%\includegraphics[width=4cm]{figures/Logo}\\[1.5cm] 
\Huge 
ewrqwru\\
rewtzhj\\
àèààvséjefwh\\[1.5cm]
\texttt{Nom du département}\\[1cm]  
%\includegraphics[width=10cm]{figures/1}\\[2cm] 
\large 
%Auteur~:~\textsc{votre nom}\\ 
Date~:~\today\\[1cm]
\end{center} 

\tableofcontents
\newpage

\section{première section}

...

\end{document}

Figure psTricks

Fichier modèle

Pour faire une figure psTricks. A compiler avec fichier tex2pdf.sh

Warning

Essayer toujours de travailler en encodage utf8, en partant du modèle en utf8.

\documentclass{article}
\usepackage[T1]{fontenc}
%\usepackage[latin1]{inputenc} % changer si ça bug en utf8
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{pstricks,pst-node}
\usepackage{xifthen}
\usepackage{longtable}
\usepackage{array}
\usepackage{hyperref}

\begin{document}
\thispagestyle{empty}

\begin{pspicture}

  ...

\end{pspicture}
\end{document}

Variante A

  1. Copier le fichier tex2pdf.sh dans le même répertoire du fichier .tex de la figure

  2. Dans un prompt Anaconda, par exemple et à condition d’avoir installer MiKTeX et réglé le PATH, tapez:

tex2pdf.sh nom_fichier (sans l'extension .tex)
Explication du fichier tex2pdf.sh
#!/bin/bash
latex -shell-escape $1.tex
dvips -E -o mafigure.eps *.dvi
ps2epsi mafigure.eps mafigure_tmp.eps
mv mafigure_tmp.eps mafigure.eps
mv mafigure.eps $1.eps
epstopdf $1.eps
rm $1.eps
rm $1.aux
rm $1.dvi
rm $1.log
rm $1.out
rm $1.tex~

Ce fichier utilise le schéma suivant pour compiler:

latex -> dvips -> ps2epsi -> epstopdf

ps2epsi sert à enlever le blanc autours de la figure. Ensuite grâce au rm, il efface les fichiers non désirables.

Variante B

Pour créer des figures pstricks j’utilise emacs pour compiler en xelatex et TeXworks pour voir le résultat compilé en mettant la fenêtre texwork à côté de celle de emacs.

Voir le résultat compilé avec xelatex avec TeXworks)
  1. clique droit sur le pdf

  2. ouvrir avec

  3. TeXworks - a graphical user interface to the typesetting system TeX and its extensions

  4. placer la fenêtre à coté de celle de emacs

  5. en compilant avec C-c-c, la fenêtre TeXworks se rafraîchit automatiquement

    ../_images/pstrick_xelatex.png
Cropper automatiquement un pdf

Pour enlever le blanc autours d’une figure, utiliser le service en ligne pdfresizer. Selectionner automatique pour vraiment enlever tout le blanc autours d’une figure. L’inconvénient est qu’il y aura plus de marge entre le texte et la figure, il faudra insérer une ligne vide.

Redessiner sur un pdf :

  1. convertir le pdf en .eps dans une console Unix en tapant :

    pdftops -eps fichierpdf.pdf
    

    Note

    remarque cette commande marche uniquement sur un pdf d’une page seulement, si le pdf contient plusieurs pages, il faudra au préalable extraire la page qui nous intéresse. Pour ce faire, voir Extraction d’une page d’un document pdf

  2. utiliser le fichier FicViePSTriBox.tex téléchargeable depuis ici

  3. pour créer le pdf directement utiliser XeLaTeX (voir Compilation avec XeLaTeX depuis emacs)

  4. pour visualiser le résultat après un C-c C-c, ouvrir le .tex avec TeXworks et choisir XeLaTeX cela va ouvrir une fenêtre pour voir le pdf créer

  5. rogner le pdf avec Briss (voir BRISS)

Sur un print-screen avec psTricks :

  1. faire un print-screen (voir Faire un print-screen)

  2. ouvrir GIMP

  3. enregistrer sous .eps

  4. utiliser le fichier FicViePSTriBox.tex situé ici

  5. pour créer le pdf directement utiliser XeLaTeX (voir Compilation avec XeLaTeX depuis emacs)

  6. pour visualiser le résultat après un C-c C-c, ouvrir le .tex avec TeXworks et choisir XeLaTeX cela va ouvrir une fenêtre pour voir le pdf créer

  7. rogner le pdf avec Briss (voir BRISS)

Centrer la figure (pour les grosses figures)

Mettre dans le préambule :

\setlength{\topmargin}{-2cm}
\setlength{\evensidemargin}{-1cm}
\setlength{\oddsidemargin}{-3cm}

pour modifier les marges.

Note

Il arrive que cela génère une page blanche avant la figure et la page comprenant la figure soit numérotée. (malgré d’avoir utilisé la commande \thispagestyle{empty}) On peut utiliser la commande suivante :

\usepackage{nopageno}

Diagramme de flux

Pour dessiner un diagramme de flux ou flow chart, j’utilse pasmatrix pour le placement des symboles. Voici les fichiers et répertoire nécessaire pour ce projet.

../_images/Capture11.PNG ../_images/Capture2.PNG

Le fichier FlowChart.tex a été compilé avec le script tex2pdf.sh dans un prompte Anaconda. La plupart des symboles sont présents, mais d’autres peuvent bien-sûr être rajoutés. (à chercher sur le net)

Voici le résultat:

../_images/Capture3.PNG

Et le code source:

\documentclass{article}
\usepackage[T1]{fontenc}
%\usepackage[latin1]{inputenc} % changer si ça bug en utf8
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{pstricks,pst-node}
\usepackage{xifthen}
\usepackage{longtable}
\usepackage{array}
\usepackage{hyperref}

\graphicspath{{./symboles/}} %les symboles du flow chart sont à mettre
                             %dans ce répertoire comme les B.eps,
                             %BR.eps, ...

\newcommand{\B}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{B.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{B.eps}\Large\raisebox{4pt}#1}}}

\newcommand{\BR}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{BR.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{BR.eps}\Large\raisebox{1pt}#1}}}

\newcommand{\C}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{C.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{C.eps}\Large\raisebox{4pt}#1}}}

\newcommand{\CH}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{CH.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{CH.eps}\Large\raisebox{1pt}#1}}}

\newcommand{\E}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{E.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{E.eps}\Large\raisebox{2pt}#1}}}

\newcommand{\EV}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{EV.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{EV.eps}\Large\raisebox{2pt}#1}}}

\newcommand{\F}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{F.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{F.eps}\Large\raisebox{4pt}#1}}}

\newcommand{\I}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{I.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{I.eps}\Large\raisebox{1pt}#1}}}

\newcommand{\M}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{M.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{M.eps}\Large\raisebox{1pt}#1}}}

\renewcommand{\P}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{P.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{P.eps}\Large\raisebox{1pt}#1}}}

\newcommand{\PM}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{PM.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{PM.eps}\Large\raisebox{1pt}#1}}}

\renewcommand{\S}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{S.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{S.eps}\Large\raisebox{1pt}#1}}}

\newcommand{\HG}[1][]{\ifthenelse{\isempty{#1}}{\fbox{\includegraphics[width=0.5cm]{HG.eps}}}%
  {\fbox{\includegraphics[width=0.5cm]{I.eps}\huge\raisebox{1pt}#1}}}

\newcommand{\Z}{[mnode=dot] Z}   

\begin{document}
\thispagestyle{empty}

\begin{pspicture}

  \small
\rput[lb](-4,-5){
\begin{psmatrix}[mnode=r,colsep=0.8cm,rowsep=0.6cm,nodealign=true] 
  %1    2     3     4          
     & \B               \\%1 
     & \Z               \\%2
     & \I[1] &    &\Z   \\%3  
     & \S[1]            \\%4
     & \S[2]            \\%5
     & \S[3]            \\%6
     & \E               \\%7
     & \I[2]            \\%8
\C[1]&       &\P        \\%9
\Z   &       &\HG       \\%10 
\I[3]&                  \\%11
\C[2]                   \\%12
&&\Z                    \\%13  
\psset{arrows=->}
% Remarque ci-dessous ce ne sont pas des coordonnées mais la position
% dans la matrice, par exemple {1,2} 1 est la première ligne et 2 la
% deuxième colonnne.
 \ncline{1,2}{3,2}  % B à  I1  
 \ncline{3,2}{4,2}  % I1 à S1
 \naput[labelsep=1.5pt]{\textcolor{red}{OUI}}
 \ncline{4,2}{5,2}  % S1 à S2
 \ncline{5,2}{6,2}  % S2 à S3
 \ncline{6,2}{7,2}  % S3 à E
 \ncline{7,2}{8,2}  % E à I2
 \ncangle[angleA=180,angleB=90,arrows=->]{8,2}{9,1} % I2 à C1
 \nbput[labelsep=1.5pt,npos=0.35]{\textcolor{red}{NON}}
 \ncline{9,1}{11,1}  % C1 à I3
 \ncline{11,1}{12,1}  % I3 à C2
 \naput[labelsep=1.5pt]{\textcolor{red}{OUI}}
 \ncangle[angleA=0,angleB=90,arrows=->]{8,2}{9,3} % I2 à P
 \naput[labelsep=1.5pt,npos=0.35]{\textcolor{red}{OUI}} 
 \ncline{9,3}{10,3}  % P à HG
 \ncline{-}{10,3}{13,3}  % HG à noeud
 \ncangle[angleA=-90,angleB=180,arrows=-]{12,1}{13,3} % C2 à noeud
 \ncangle[angleA=0,angleB=-90,arrows=-]{13,3}{3,4} % noeud à noeud
 \ncangle[angleA=90,angleB=0,arrows=->]{3,4}{2,2} % noeud à noeud
 \ncline{-}{3,2}{3,4} % I1 à noeud
 \naput[labelsep=1.5pt,npos=0.25]{\textcolor{red}{NON}}
 \ncbar[angleA=0,angleB=0,arm=1,arrows=->]{11,1}{10,1} % I3 à noeud
 \naput[labelsep=1.5pt,npos=0.45]{\textcolor{red}{NON}}
\end{psmatrix}}

\rput[lb](4,-5){
\begin{tabular}{>{\centering}m{1cm}m{7cm}} %sert à définir une police
  \label{repsd}
  \B    & Début \\\\
  \I[1] & olweolsnkécjas \\\\
  \I[1] & ewosxcmklwéo? \\\\
  \S[1] & wesege \\\\
  \S[2] & wefgfedfvg\\\\
  \S[3] & tzjughmozhl\\\\ 
  \E & tziuimbngf\\\\ 
  \I[2] & éàlgfhjhz\\\\
  \C[1] & aertéoiudsf.,nw98\\\\ 
  \I[3] & kljrsdmévélj023\\\\
  \C[2] & léjwqepr987usdkàretg90è\\\\
  \P    & léj34p789udsflnjewf\\\\
  \HG & léj4pr82éljdfsrnjlmkdsfpo\\
\end{tabular}}

\end{pspicture}
\end{document}

Regex

Java Script

caractère seul

  • d -> 0-9 D -> pas des chiffres

  • w -> A-Z a-z 0-9 W -> pas des lettres ni des chifres

  • s -> espace, tabulation S tout sauf des espaces

  • . -> n’importe quel caractère

Quantificateur

  • * -> 0 ou plus

  • + -> 1 ou plus

  • ? -> 0 ou un seul

  • {min,max} -> entre min et max fois

  • {n} -> n fois

  • ? si appairé avec un quantificateur alors ce ne sera pas gridy. gridy veut dire qui prendre la plus grande correspondance

Exemple pour Gridy :

../_images/Regex_gridy1.PNG

pour enlever le gridy :

../_images/Regex_not_gridy.PNG

Position

^ -> début de ligne $ -> fin de ligne b -> word boundery

Exemple pour b :

../_images/RegexWordBoundery1.PNG ../_images/RegexWordBoundery2.PNG

Classe de caractère

[abc] -> soit un a un b ou un c [-.] -> le point n’est pas un charactère meta mais un point litéral (car il est compris dans une classe) on échappera avec si l’on veut un point litéral et qu’il n’est pas dans une classe.

“-” si il est au début de la classe il sera pris commme un trait d’union litéral. Par-contre s’il est au centre de par exemple [a-d] il sera interpréter comme un interval ici a ou b ou c ou d “^” s’il est au début alors ça inverse, par exemple [^a-c] alors tous les autres caractères seront pris sauf a,b,c.

Exemple :

../_images/Regex1.PNG

Altération

(net|com) si on veut “net” ou “com”

Groupe

../_images/Regex_group.PNG

on appellera $1 $2 suivant qu’il y plusieurs groupe $0 représente tout ce qui a été trouvé

Back Reference

../_images/Regex_Back_Reference.PNG

Implémentation de Regex dans Java Script

variable string:

var s = “hello”

variable regex :

var r = /hello/

../_images/Regex_test.PNG

Flags :

g pour global

/d{3}/g

i pour case insensitive

match :

../_images/Regex_match.PNG

match construit un array avec g, mais si la regex comporte un groupe () alors si le flag g est présent le groupe ne sera pas mis dans l’array

../_images/regex_match_group.PNG

pour que même le groupe soit pris dans l’array, il faut utiliser r.exec(s) et faire une boucle:

var results;
while (results=r.exec(s){
createP(results[1]);
}

D3

Pour arrondir les chiffres

http://bl.ocks.org/zanarmstrong/05c1e95bf7aa16c4768e

bash

Echo

Afficher des variable système

echo PATH
echo HOME

pour remplir un fichier

echo -e "Qte\tPrix\tTotal\n\n3\t5\t15frs" > fichier

Note

On peut afficher le contenu d’un fichier avec la commande cat nom_de_fichier. Si l’on veut rajouter des lignes au fichiers on peut utiliser >> Mais dangereux car on a vite fait d’oublier de mettre le deuxième >.

Sed and Awk

Les différents moyens d’entrer du code

awk -f nom_du_script fichier_d_entree

En tapant tout le code dans un terminal :

awk '
BEGIN{
print "Hello
World"}
'

Warning

Ne pas oublier l’espace entre awk et '

En tapant le code dans un fichier avec la commande awk insérée dans le fichier :

Si le code contient BEGIN et une expression régulière alors on entrera :

awk 'BEGIN { print "debut"}
$0 ~ /Drive/ {print "sdfsd"}' nom_du_fichier_d_entree

Si le code contient pas d’expression régulière mais un BEGIN, on entrera :

awk 'BEGIN { print "debut"}
{print "sdfsd"}' nom_du_fichier_d_entree

Si le code ne contient pas de BEGIN alors on entrera :

awk '{
print "Hello World"
}
' nom_du_fichier_d_entree

Passage des variables

Voici un exemple pour le passage des variables d’entrée d’un programme awk entrer dans un fichier qui s’appelle glitch.

awk 'BEGIN { FS = "\n"; RS = ""; ORS = "\n\n"}
$0 ~ search {print $0}' search=$1 $2

Ici on a mis le séparateur de champ FS à un retour de ligne et le séparateur d’enregistrement RS à une ligne vide, ceci afin de pouvoir prendre en compte un fichier à données en bloc appelé glitch.data dont voici un extrait :

machine       Sun 3/75
              8 meg memory
              Prone to memory glitches
              more info
              more info

sadlefsdaf    siwefo
              asdlfa
              vmasefsdae
              glitche wefsd
              sdafsdf
ziweower      wwerwe 3234
              sdfljkljké
              asdfvm78
              weojwd
              omcvljdoji

En tapant la commande :

glitch glitc glitch.data

cela va donner :

machine       Sun 3/75
              8 meg memory
              Prone to memory glitches
              more info
              more info

sadlefsdaf    siwefo
              asdlfa
              vmasefsdae
              glitche wefsd
              sdafsdf

Les fonctions

Emplacement pour déclaration des fonctions

awk '
 function insert (STRING, POS, INS) {
 before = substr("Hello",1,POS)
 after = substr("Hello",POS+1)
 return before INS after
 }
BEGIN{
   print insert($1, 4, "XX")
}'

Divers exemples

Pour inverser les colonnes et les lignes

awk  '
BEGIN{FS=";"}
{
 for ( i = 1; i <= NF; ++i ){
     matrice[NR,i] = $i
     gsub(/\r/,"") #\r est le retour de ligne \n ne fonctione pas
 }
 }

 END {
     for ( j = 1; j <= NF; ++j ){
         for ( i = 1; i <= NR; ++i ){
             printf ("%s;",matrice[i,j]) #point virgule aux séparateurs de champs à la sortie
         }
         if ( j < NF )
         print("\r")
     }

 }' sp.txt > Result

reStructuredText

Installation

  1. installer Anaconda

  2. installer VS code

  3. modifier le path windows pointer les répertoires suivants :

    1. anaconda3/Scripts

    2. anaconda3 (c’est possible qu’il n’est pas nécessaire de pointer sur celui-ci)

Création d’un nouveau document

  1. ouvrir Anaconda Prompt

  2. aller dans le bon répertoire (tapez d: pour changer de partition)

  3. une fois dans le répertoire où l’on veut mettre notre document, tapez :

    sphinx-quickstart
    
  4. aux différentes questions répondre comme ci-dessous :

    > Separate source and build directories (y/n) [n]: y

    > Name prefix for templates and static dir [_]:

    > Project name: Mon nom de projet

    > Author name(s): Alpiq AG

    > Project release []: 1

    > Project language [en]: fr

    > Source file suffix [.rst]:

    > Name of your master document (without suffix) [index]:

    Sphinx can also add configuration for epub output: > Do you want to use the epub builder (y/n) [n]:

    Indicate which of the following Sphinx extensions should be enabled: > autodoc: automatically insert docstrings from modules (y/n) [n]:

    > doctest: automatically test code snippets in doctest blocks (y/n) [n]:

    > intersphinx: link between Sphinx documentation of different projects (y/n) [n]:

    > todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: y

    > coverage: checks for documentation coverage (y/n) [n]:

    > imgmath: include math, rendered as PNG or SVG images (y/n) [n]: y

    > mathjax: include math, rendered in the browser by MathJax (y/n) [n]: y

    > ifconfig: conditional inclusion of content based on config values (y/n) [n]: y

    > viewcode: include links to the source code of documented Python objects (y/n)[n]:

    > githubpages: create .nojekyll file to publish the document on GitHub pages (y/n) [n]:

    > Create Makefile? (y/n) [y]:

    > Create Windows command file? (y/n) [y]:

  5. ajouter la ligne suivante: master_doc = 'index' sinon ça bug avec Read The Docs aussi ça plante lorsqu’on compile dans un terminal windows (cmd) ça affiche qu’un fichier dénommé contents est introuvable.

  6. tapez dans le terminal :

    D:\tmp\sphinxTxt>make html
    
  7. ouvrir Visual Studio Code

  8. ouvrir le répertoire du projet et non le fichier .rst (File -> Open Folder)

  9. il se peut que l’on soit demandé à selectionner le conf.py, selectionnez celui qui se trouve dans le répertoire du projet

  10. pour ouvrir la prévisualisation cliquer sur le symbole afficher sur la figure ci-dessous. Sinon ouvrir le html dans un explorateur qui se trouve dans le répertoire _build -> html

cette image montre où l'on doit cliquer pour ouvrir la fenêtre de prévisualisation
  1. pour l’édition, j’utilise emacs, ouvrir le fichier index.rst

Changement de Thèmes

  1. choisir son thème ici. Pour cet exemple, j’ai choisi sphinx_rtd_theme car il est “mobile friendly

  1. se connecter à internet (swisscom) et tapez dans une console :

    pip install sphinx_rtd_theme
    
  2. ouvrir le conf.py et mettre html_theme = 'sphinx_rtd_theme'

Compilation

Dans un Anaconda prompt tapez :

make html

Pour voir la doc dans un navigateur internet. Ceci créera un répertoire build et y placera deux autres répertoires : html et doctrees Dans le répertoire html on trouvera le fichier index.html. En cliquant sur ce dernier cela va ouvrir la doc dans un navigateur internet. Le répertoire doctrees sert pour la table des matières.

ou

make latex

ou

make latexpdf

Note

Après la compilation, il se peut que la table des matières ne soit pas dans l’ordre ou que toutes les sections suivantes ne soient affichées. Dans ce cas, il faut supprimer le répertoire build et refaire une compilation.

Traduction

-doc
  .git
  .gitignore
  make.bat
  Makefile
  -build
     -doctrees
     -gettext
        index.pot
     -html
     -latex
  -sources
     -locale
        -de
           -LC_MESSAGES
              index.po
        -fr
           -LC_MESSAGES
              index.po
     -dir
        -images
           -de
              -1.png
           -fr
              -1.png

Les textes à traduire se trouvent dans les fichiers .po

Liens à traduire et problèmes

Pour les liens à traduire qui sont internes au document et qui n’ouvrent pas de nouvelle fenêtre ça fonctionne bien. Par-contre pour les liens qui ouvrent une nouvelle fenêtre comme dans le code suivant:

This is in my .rst:

On ouvre une nouvelle fenêtre |lien|

.. |lien| raw:: html

  <a href="http://python.physique.free.fr/aide/_sources/Partie1.txt"
  target="_blank">ici</a>

and this is the translated file:

#: ../../source/consigne_indispo/consigne_indispo.rst:4
msgid "On ouvre une nouvelle fenêtre |lien|"
msgstr "Wir öffnen ein neues Fenster |lien|"

The problem is that I want to translate the world "ici" also (should
be translated in "hier", but can't see it in the translated file.
  1. installer sphinx-intl

$ pip install sphinx-intl
  1. rajouter ces lignes dans le conf.py

locale_dirs = ['locale/']   # path is example but recommended.
gettext_compact = False     # optional.
gettext_additional_targets = ['image', 'index', 'literal-block'] #
allows images to be translatable. Cette ligne permet de traduire
les "alt" ou "les légendes"
figure_language_filename = "{path}{language}/{basename}{ext}"
  1. make gettext
    
  2. génération des fichiers po (dans le cas suivant pour l’allemand et pour le japonais)

sphinx-intl update -p build/gettext -l de -l ja

sitôt fait, le fichier po se trouve dans le répertoire ./locale/de/LC_MESSAGE`

  1. traduire le fichier po

    exemple :

msgid "Available builders"
msgstr "<FILL HERE BY TARGET LANGUAGE>"

Dans le cas où il y a plusieurs lignes :

msgid ""
"These are the built-in Sphinx builders. More builders can be added by "

msgstr ""
"FILL HERE BY TARGET LANGUAGE FILL HERE BY TARGET LANGUAGE FILL
HERE "
"BY TARGET LANGUAGE :ref:`EXTENSIONS <extensions>` FILL HERE."
  1. génération du document traduit, saisir dans le Anaconda Powershell Prompt Bien faire dans ce Prompt car dans l’autre la commande Set... ne fonctionne pas. Ici on veut générer le html pour l’allemend (de)

> Set-Item env:SPHINXOPTS "-D language=de"
> .\make.bat html
  1. génération d’une langue supplémentaire : il suffit de remplacer de par en par exemple

  2. si l’on a fait des mises à jour, il faudra faire les étapes 3) et 4) pour regnérer le .po. Si les .po ne subissent pas de changement il ne seront pas effacés ni regénérés.

Note

Il arrive parfois que le mot fuzzi apparaisse pour une raison que je ne saurai expliquer. Peut être est-ce dû aux longues lignes? Pour que ça refonctionne, ma technique est de supprimer la ligne comportant `fuzzi.

../_images/Capture21.PNG ../_images/Capture31.PNG

Images différentes pour chaque langue

figure_language_filename = "{path}{language}/{basename}{ext}" à mettre tel quel dans le fichier conf.py

gettext_additional_targets = ['image', 'index', 'literal-block'] # allows images to be translatable

cette dernière ligne je ne sais pas encore à quoi elle sert, mais je l’ai mise quand même.

Important

Il est impératif de créer à l’endroit où il y a le fichier .rst un répertoire se nommant images (et pas figure par exemple sinon ça marche pas).

  1. créer un répertoire se nommant images

  2. à l’intérieur de ce répertoire créer des répertoires pour chaque langue. Par exemple pour le français et l’allemand :

    • fr

    • de

    Je ne sais pas si l’abréviation de la langue est importante (fr et de)

  3. dans chacun de ces répertoire l’image bien que différente, doit être nommée à l’identique. ex. dans le répertoire fr une image nommée 1.png se retrouvera aussi dans le répertoire de avec le même nom 1.png.

Pour plus d’information

sphinx-doc

Mise en forme

Numérotation chapitre, section, etc…

  • # pour les parties

  • * pour les chapitres

  • =, pour les sections

  • -, pour les sous-sections

  • ^, pour les sous-sous-sections

  • ", pour les paragraphes

Listes et sous-listes

* une puce "*"
  - une sous-liste avec "-"
    + à nouveau une sous-liste avec "+"
  - une autre option
1. Liste numérotée "à  la main".
2. Deuxième item.

#. Liste numérotée automatiquement.
#. Deuxième item.
  1. Liste numérotée “à la main”.

  2. Deuxième item.

  3. Liste numérotée automatiquement.

  4. Deuxième item.

Les tableaux

+------------------------+------------+----------+
| Header row, column 1   | Header 2   | Header 3 |
+========================+============+==========+
| body row 1, column 1   | column 2   | column 3 |
+------------------------+------------+----------+
| body row 2             | Cells may span        |
+------------------------+-----------------------+


====================  ==========  ==========
Header row, column 1  Header 2    Header 3
====================  ==========  ==========
body row 1, column 1  column 2    column 3
body row 2            Cells may span columns
====================  ======================

donnera :

Header row, column 1

Header 2

Header 3

body row 1, column 1

column 2

column 3

body row 2

Cells may span

Header row, column 1

Header 2

Header 3

body row 1, column 1

column 2

column 3

body row 2

Cells may span columns

Insertion d’une figure

Si le répertoire nommé figures est au même endroit où il y a le fichier index.rst

.. image:: /figures/IconePrevisualisation_cropped.png
    :scale: 80 %
    :align: center
Image svg

Pour avoir une image non pixelisée, le format svg peut être utilisé.

J’utilise l’adresse suivante (cliquer ici) pour convertir le format pdf en svg

Insérer une ligne vide

Utile par exemple quand on insère une figure croppée automatiquement (pas de marge blanche autours de la figure). Ainsi le texte ne sera pas trop de la figure.

.. # define a hard line break for HTML
.. |br| raw:: html

 <br />

Mettre à l’emplacement où l’on veut avoir une ligne blanche :

|br|

Surbrillance d’un texte

Surbrillance d'un texte

Tapez :

``Surbrillance d'un texte``

Pour afficher un bloc avec du code

POUR AFFICHER CECI (un bloc avec du code)

Tapez :

::

 POUR AFFICHER CECI (un bloc avec du code)

Pour créer un lien à l’intérieur d’un document

interne à la page ou à une autre page .rst

Warning

Pour que le lien fonctionne il faut bien effacer le répertoire build avant (rmdir /s build) et refaire une compilation (make html).

label (à mettre où l’on veut tomber) :

.. _Nom du lien:

Par exemple si on veut que ça tombe vers une section, on le placera une ligne avant la section.

.. _Nom du lien:

reStructuredText
================

ref (à écrire où on veut mettre le lien)

Pour plus d'information veuillez vous référer à :ref:`Nom du lien`.

Ceci donnera :

Pour plus d’information veuillez vous référer à Les fonctions.

Pour créer un lien à une page internet

En cliquant sur le lien, cela va ouvrir une nouvelle fenêtre dans le navigateur.

En cliquant |lien|
.. |lien| raw:: html

  <a href="http://python.physique.free.fr/aide/_sources/Partie1.txt"
  target="_blank">ici</a>

Warning

Ne pas oublier d’indenter <a href…

On peut très bien écrire directement :

http://home.citycable.ch/windwaver/MesSources/

mais cela ne va pas ouvrir une nouvelle fenêtre dans le navigateur.

Commentaires

  • Pour commenter une ligne, mettre deux points et un espace.

  • Pour commenter un bloc, mettre deux points et indenter le bloc en dessous.

Mettre en évidence une chose importante

.. warning::
   Mettre ici une chose importante

ce qui donne :

Warning

Mettre ici une chose importante

.. hint::
   Une chose moins importante

ce qui donne :

Hint

Une chose moins importante

Commande

Qui donne

Couleur

.. warning::

‘i’ int32

Rouge

.. note::

note

Grise

.. tip::

Astuce

Grise

.. caution::

Prudence

Grise

.. error::

Erreur

Grise

.. hint::

Indice

Grise

Pour insérer du code à partir d’un fichier

Tapez le code suivant :

.. literalinclude:: /IT/sources/exemple_graphique01.py

Ce qui donnera :

# -*- coding: utf-8 -*-
"""
Exemple de plot
"""

from __future__ import division
from scipy import *
from pylab import *

x = linspace(0,10,400)
y = sin(x)*exp(-x/5)
plot(x,y)
show()

Pour insérer une vidéo

Tapez le code suivant :

.. raw:: html

    <iframe width="560" height="315"
    src="https://www.youtube.com/embed/UaIvrDWrIWM" frameborder="0"
    allowfullscreen></iframe>

Ce qui donnera :

Pour insérer des formules mathématiques

Normalement, on peut inclure des maths avec :math:`code LaTeX` ou alors avec .. math:: code LaTeX sur une seule ligne

.. math::

   a^2

Ce qui donne :

\[a^2\]

Création du document pdf

  1. à l’aide du prompt Anaconda se déplacer dans le répertoire du projet (où il y a le .rst)

  2. tapez make latexpdf cela va créer un répertoire latex dans le répertoire _build

  3. ouvrir le fichier .tex dans le répertoire latex avec emacs

  4. compiler

Divers liens utiles

  1. python.physique

  1. thomas-cokelaer

  1. sphinx-doc

  1. draft-edx-guide

  1. complang

  1. docutils.sourceforge

Visual Studio Code

Configuration

fichier JSON de configuration

../_images/Capture12.PNG ../_images/Capture22.PNG

Pour les lignes longues on peu mettre dans settings Word Wrap à on.

emmet est installé par défaut. Il permet de ne pas écrire tout la syntaxe balistique. Par exemple si on veut écrie <h1></h1>, il suffit d’appuyer sur h ensuite sur ce qui est proprosé faire une tabulation à droite ou enter.

Extension

Prettier - Code formatter

Permet d’aligner le code à la sauvegarde

../_images/Capture32.PNG

Une fois installé, il faut aller dans settings

../_images/Capture4.PNG

Il faut peut-être reloader l’extension si demandé.

Taper “format” dans la zone recherche

../_images/Capture5.PNG

Cocher Format On Paste et Format On Save

../_images/Capture6.PNG

Et maintenant à chaque enregistrement du fichier le texte se formate.

keyboard shortcuts

../_images/Capture7.PNG

html

  • HTML HYPER TEXT MARKUP LANGUAGE

  • RESPONSIBLE FOR WEBPAGE STRUCTURE

  • <element>content</element>

  • <h1>Heading</h1> === Heading Element

  • <p>Paragraph</p> === Paragraph Element

  • <img src=”…”> === Image Element

  • <br /> === Line Break

../_images/Capture13.PNG

<!DOCTYPE html>

Pour mettre en entête standard dans index.html on tapera ! et return emmmet insérera l’entête standard pour le fichier index.html.

Toutes les pages html suivent la même structure. Tout en haut nous avons la déclacration DOCTYPE qui dit au browser en quel version du language html la page est écrite. Ensuite nous avons la balise html qui englobe tout notre code de la page. Celle possède au moin un head et un body. Donc après l’élément html nous avons l’élément head qui contient des informations de la page comme par exemple le titre de la page, les métadatas, et les links vers source extérieures comme les fichiers de style css et les fichiers java script. Le contenu de head ne sera pas visible dans la page. Le body contiendra headings, paragraphes, links.

Maintenant que nous connaissons les bases du contenu d’une page, mettons ceci dans notre première page. En tapant <, VS va nous proposer !DOCTYPEhtml qui est la version 5 de html. Ensuite vient la balise html. Puis body dans lequel on met un h1 avec du texte. Enchaînant avec un paragraph.

../_images/Capture23.PNG ../_images/Capture33.PNG

Grâce à l’extension live server notre résultat est affiché automatiquement après un save.

../_images/Capture41.PNG ../_images/Capture51.PNG

En mettant autosave notre résultat sera affiché en live.

Tout le contenu que l’on a tapez précédemment peut être simplifié par emmet. Tapez simplement ! et enter.

../_images/Capture61.PNG

Pour l’instant, on fera attention que pour title et se qui se trouve dans le body.

headings

../_images/Capture71.PNG ../_images/Capture8.PNG

paragraph

Pour info html is white space collapsing, c’est-à-dire que html ignore les espaces que l’on aurait fait en trop entre deux mots. Si l’on veut vraiment un espace plus grand, on verra ceci plus tard.

Regardons maintenant comment on peut écrire un bout de texte (n’importe quel paragraphe) rapidement. Tapez : Lo et choisissez lorem. On peut choisir le nombre de mots que l’on souhaite afficher en tapant lorem50 pour 50 mots.

../_images/Capture9.PNG ../_images/Capture10.PNG

Images

Si l’on veut des images quelconques, on peut chercher dans google udemy image.

Tapez img et enter on doit indiquer dans src le chemin où se trouve l’image sur le disque. et alt est renseigné pour que si l’image ne peut être trouvée, un texte alternative est affiché à la place de l’image.

../_images/Capture111.PNG

Il est préférable d’utiliser le relative path : ./

On peut très bien pointer sur l’adresse d’une image sur le web: dans ce cas il faut faire un clique droite sur l’image est faire copier l'adresse de l'image. L’inconvénient de cette technique est d’avoir une adresse monstrueuse de l’image. Il existe des sites qui propose des images sans licences dont l’adresse est plus simple. Comme par exemple :

Enregistrer l’image dans le dossier.

Modifier la taille

../_images/Capture121.PNG

On a prit une grand image et l’affichage est tronqué. Pour ajuster la taille de l’image, on pourrait très bien diminué sa taille avec un logiciel, mais ici nous allons utiliser les attributs d’html pour modifier la taille de l’image.

Pour mettre l’image à la même taille que la première nous allons utiliser Visual Studio Code pour en ouvrant la première image.

../_images/Capture131.PNG

et relever la valeur de 246x205 affichée dans le bandeau inférieur. Et pour la plus grande image nous avons 5999x3681

On rajoute un attribut width=”246” et le tour est joué.

../_images/Capture14.PNG ../_images/Capture15.PNG

Il y a un autre attribut qui est height mais si on met celui-ci l’image sera déformée, donc garder uniquement width.

Il y a un grand problème encore quand le browser render l’image bien qu’elle aie diminué en taille elle sera toujours chargée avec un grande taille d’octets. Ce qui va réduire le user experience. Utiliser un logiciel libre comme gimp et réduire la taille directement à la bonne taille et ensuite enlever le width.

path

Créons un dossier images avec les images dedans. Et modifions le chemain des images.

../_images/Capture16.PNG

Commentaires

../_images/Capture17.PNG

Raccourci clavier : appuyer en même temps sur ctrl alt et “a”

line break

<br>

sub and sup

../_images/Capture27.PNG ../_images/Capture28.PNG

strong

../_images/Capture29.PNG ../_images/Capture30.PNG

em

../_images/Capture311.PNG ../_images/Capture321.PNG

Normalement, nous utilisons ces éléments dans le css.

Caractères spéciaux

Liste

Liste non numérotée

../_images/Capture35.PNG ../_images/Capture36.PNG
Exemple d’utilisation des listes non numérotée

Pour faire un menu. Pour l’instant le style n’est pas bon, mais nous verrons plus tard comment l’améliorer.

../_images/Capture37.PNG ../_images/Capture38.PNG

Liste numérotée

../_images/Capture39.PNG ../_images/Capture40.PNG

Liste imbriquée

../_images/Capture411.PNG ../_images/Capture42.PNG

Table

../_images/Capture43.PNG ../_images/Capture44.PNG

avec:

  • th pour table head

  • tr pour table row

  • td pour table data

Form

../_images/Capture44.PNG

Pour l’introduction des formulaires nous ne nous s’occuperons pas de acction=”” ni de method=”” car ces attributs sont pour la collecte de donnée avec par exemple php ou JS.

Pour la collecte de données nous pourrions utilisé https://formspree.io qui nous enverrais les données par email.

../_images/Capture46.PNG

action est utlisée pour dire à quel email les données collectées doivent être envoyée. method="POST" est utilisée pour envoyer les données sur un server.

input a plusieurs type comme email, button, checkbox. Le plus courant est le type text, il a deux attributs name et id. name est l’endroit où l’on veut stocker les données. id est utilisé avec label que nous montrerons plus loin.

input type=”text”

../_images/Capture47.PNG ../_images/Capture48.PNG

Nous voyons le champs dans lequel on peut écrire quelque chose, mais ne se passe.

submit button

L’élément qui vient souvent avec un formulaire est le bouton submit. Pour l’implémentation de celui-ci nous avons deux options.

button avec type=”submit” et entre button nous pouvons mettre le texte du button.

../_images/Capture49.PNG ../_images/Capture50.PNG

si l’on veut un espace entre les deux éléments on peut utiliser <br>

../_images/Capture52.PNG

Plus nous utilserons <div> pour un meilleure rendu.

Pour l’instant les données entrées sont retournée à la même page.

En tapant eric, nous aurons name=eric

../_images/Capture53.PNG

Les champs se vident car nous avons appuyer sur le bouton submit.

La deuxième variant pour mettre un bouton submit est d’utiliser input avec type=”submit”.

../_images/Capture54.PNG ../_images/Capture55.PNG

On constate que le texte sur le bouton s’est mis tout seul Un mot en français “Envoyé”.

label

Parlons maintenant du id. id vient avec label. On peut mettre un label à un champs.

../_images/Capture56.PNG ../_images/Capture57.PNG

input password et email

Regardons maintenant à d’autre input comme password et email.

placeholder

Au lieu de label nous pouvons aussi mettre un paragraphe. Mettons un placeholder qui écrit à l’intérieur du champs ce que l’on veut.

Mettons l’input email. Remarquons que si l’email n’est pas correctememnt formater, il y aura un message d’alerte.

value

Parlons de l’attribut value qui sert à coder en dure. Le champs est directement rempli par value. Aussi on peut mettre type=”submit” value pour afficher un autre texte sur le bouton submit.

../_images/Capture58.PNG ../_images/Capture59.PNG

textarea, bouton radio

input ne sont pas les seules élément que l’on peut mettre dans un form.

textarea, qui nous permet d’écrire plus de mots. Les attributs cols et rows permettent d’ajuster la taille de textarea.

Nous avons aussi les boutons radio. On mettra value pour travailler la collecte des inputs. Attention de bien écrire name avec le même nom car sinon nous pourrons sélectionner plusieur bouton en même temps.

../_images/Capture60.PNG ../_images/Capture611.PNG

checkbox

Voici comment implémenter les checkbox:

../_images/Capture62.PNG ../_images/Capture63.PNG

Il y a aussi un attribut checked pour dire que la case est cochée par défaut, il est possible de la déchecker.

../_images/Capture64.PNG ../_images/Capture65.PNG

On remarque que des que l’on appuie sur le submit button les données ne sont envoyées à nulle part, mais on constate que l’adresse (url) se modifie avec les données saisies dans le forulaire.

select

C’est comme un drop down menu.

Documentation

Premier Projet

Etape “Home”

  1. Créons d’abord un répertoire sur le disque local avec le nom du projet. Ici le nom du répertoire sera Coffee;

  2. Dans la première ligne tapez ! et return. Emmet insérera un en-tête standard;

  3. Modifions le titre en mettant Coffe Junkie;

  4. Dans le body mettons hello world;

  5. Pour voir notre résultat faisons un clique-droite et sélectionnons Live Server;

  6. Arrangeons un peu les fenêtres. Ouvrons un deuxième instance de Chrome et écrivons l’url de Live Server. Sur un écran, on peut mettre VS prenant un peu plus de la moitié de l’écran et l’autre moitié Chrome. Dans le premier Chrome un mettra la page sur toute sa largeur afin d’avoir une vue total en largeur de la page du site que l’on va créer;

  7. Dans le répertoire Coffee, créons un nouveau répertoire images;

  8. Copions les images dans le répertoire images

    • pour le logo dans google taper coffe logo backround transparent

    • pour l’image plus grande on ira la chercher sur pexels.com

  9. Modifions trois images avec Gimp à une taille de 320px de largeur;

  10. Ecrivons le code pour insérer le logo;

  11. Un h3 pour le titre de la page

  12. Un ul pour faire la liste de navigation.

Et voici le code de notre premier étape

../_images/Capture66.PNG

Et l’apperçu

../_images/Capture67.PNG
  1. Insérons l’image backround la grande et nous voyons qu’elle est trop grand sur la fenêtre à coté VS et trop petite sur la grande fenêtre de Chrome. Normalement nous devons faire cela dans css, mais comme nous n’avons pas encore abordé ce sujet, nous mettrons la commande directement dans le html, avec l’attribut width à 100%

    ../_images/Capture68.PNG
  2. Mettons maintenant un h1 pour Feature Product

  3. Un h2 pour House Blend Coffee

  4. Une image

  5. un paragraphe avec ici une petite spécialité que l’on corrige maintenant mais normalement cela va se faire en css. Le paragraphe s’étire sur toute la largeur de la page en plein écran et c’est pas beau. On fait du inline styling en écrivant <p style=”width:50%”>

  6. un h3 pour un lien vers wikipedia, remarquer l’attribut de target=”_blank” pour que l’utilisge ouvre une nouvelle page et ne quitte notre site

  7. copions ce code pour les deux autres produits et changeons les noms et images.

  8. mettons le copyright avec &copy; pour le caractère spéciale

  9. insrérons quelques br et un lien vers le top ou logo mais étant donné que nous n’avons pas encore de id sur l’image du logo, rajoutons le maintenant

Voici le code pour cette étape:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Coffee Junkie</title>
</head>
<body>
 <img src="./images/logo.png" id="logo" alt="coffe logo">
 <h3>Coffee Junkie</h3>
 <ul>
  <li><a href="index.html">Home</a></li>
  <li><a href="about.html">About</a></li>
  <li><a href="number.html">Number</a></li>
  <li><a href="contact.html">Contact</a></li>
 </ul>
 <img src="./images/background.jpeg" width="100%" alt="coffee beans">
 <br>
 <h1>Feature Product</h1>
 <br>
  <!-- house blend -->
  <h2>House Blend Coffee</h2>
   <img src="./images/house-blend.jpeg" alt="house blend">
   <p style="width:50%">Lorem ipsum dolor sit amet consectetur adipisicing elit. Quod explicabo recusandae consequuntur dolorem accusamus dolorum itaque nisi consectetur, voluptas laudantium? Necessitatibus ducimus aperiam maiores nostrum quas? Fuga omnis possimus commodi? Id vero exercitationem, delectus quas velit optio commodi animi dignissimos repudiandae minima, provident corporis in officia officiis, nostrum distinctio quam.</p>
<h3><a href="https://www.wikipedia.org/" target="_blank">Details</a></h3>
<br>
<br>
<!-- french roast -->
<h2>French Roast</h2>
<img src="./images/french-roast.jpeg" alt="french roast">
<p style="width:50%">Lorem ipsum dolor sit amet consectetur adipisicing elit. Quod explicabo recusandae consequuntur
 dolorem accusamus dolorum itaque nisi consectetur, voluptas laudantium? Necessitatibus ducimus aperiam maiores nostrum
 quas? Fuga omnis possimus commodi? Id vero exercitationem, delectus quas velit optio commodi animi dignissimos
 repudiandae minima, provident corporis in officia officiis, nostrum distinctio quam.</p>
<h3><a href="https://www.wikipedia.org/" target="_blank">Details</a></h3>
<br>
<br>
<!-- Columbian Roast -->
<h2>Columbian Roast</h2>
<img src="./images/columbian-roast.jpeg" alt="Columbian Roast">
<p style="width:50%">Lorem ipsum dolor sit amet consectetur adipisicing elit. Quod explicabo recusandae consequuntur
 dolorem accusamus dolorum itaque nisi consectetur, voluptas laudantium? Necessitatibus ducimus aperiam maiores nostrum
 quas? Fuga omnis possimus commodi? Id vero exercitationem, delectus quas velit optio commodi animi dignissimos
 repudiandae minima, provident corporis in officia officiis, nostrum distinctio quam.</p>
<h3><a href="https://www.wikipedia.org/" target="_blank">Details</a></h3>
<br>
<br>
<br>
<br>
<br>
<p>copyright&copy;2021</p>
<h3><a href="#logo">Back To Top</a></h3>

</body>
</html>
../_images/Capture69.PNG ../_images/Capture70.PNG ../_images/Capture711.PNG

Etape “About”

Faisons maintenant la page About, qui a aussi l’image background (la toute grande) normalement on utilise du css pour définir une “background image”. Nous avons plusieurs options pour commencer cette page, soit de copier coller la page Home déjà faite à la première étage, ou soit tout réécrire d’une page blanche. Choisisson la première options.

  1. Changeons le titre en About

  2. La grande image reste et Feature Product est remplacé par About Us

  3. Effacer les 3 produits

  4. Rajoutons un paragraphe avec 500 mots avec Lorem500

Etape “Numbers”

Pour la page Numbers tout reste la même chose (entête, bas-de-page). Donc nous refaisons un copier paste, mais cette fois du contenu de la page About.

  1. Dans le head, on mettra title à Numbers

  2. Dans le body, on mettra en h1 Our Stores

  3. Insérons une table et commentaire pour notre row city avec tr

  4. th pour titre avec les 4 noms des villes et un commentaire disant que c’est la fin de la première row

  5. faisons la même chose pour la ligne mais avec td pour data

  6. comme ce tableau n’a pas fière allure nous lui appliquons du css.

../_images/Capture72.PNG ../_images/Capture73.PNG

Voici le code pour la page numbers

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Numbers</title>
</head>

<body>
 <img src="./images/logo.png" id="logo" alt="coffe logo">
 <h3>Coffee Junkie</h3>
 <ul>
  <li><a href="index.html">Home</a></li>
  <li><a href="about.html">About</a></li>
  <li><a href="numbers.html">Numbers</a></li>
  <li><a href="contact.html">Contact</a></li>
 </ul>
 <img src="./images/background.jpeg" width="100%" alt="coffee beans">
 <br>
 <h1>Our Stores</h1>
 <br>
 <table style="border:2px solid black; border-spacing:25px">
  <!-- city -->
  <tr>
   <th>City</th>
   <th>Chicago</th>
   <th>New York</th>
   <th>Los Angeles</th>
  </tr>
  <!-- end of city -->
  <!-- orders -->
  <tr>
   <td>Order</td>
   <td>125</td>
   <td>250</td>
   <td>500</td>
  </tr>
  <!-- end of orders -->
  <!-- profit -->
  <tr>
   <td>Profit</td>
   <td>$ 10,000</td>
   <td>$ 20,000</td>
   <td>$ 30,000</td>
  </tr>
  <!-- end of profit -->
 </table>
 
 <br>
 <br>
 <br>
 <br>
 <br>
 <p>copyright&copy;2021</p>
 <h3><a href="#logo">Back To Top</a></h3>
</body>

</html>

Etape “Contact”

Encore une fois nous allons copier le contenu.

Voici le code pour la page contact

<!DOCTYPE html>
<html lang="en">

<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Contact</title>
</head>

<body>
 <img src="./images/logo.png" id="logo" alt="coffe logo">
 <h3>Coffee Junkie</h3>
 <ul>
  <li><a href="index.html">Home</a></li>
  <li><a href="about.html">About</a></li>
  <li><a href="numbers.html">Numbers</a></li>
  <li><a href="contact.html">Contact</a></li>
 </ul>
 <img src="./images/background.jpeg" width="100%" alt="coffee beans">
 <br>
 <h1>Contact Us</h1>
 <br>
 <form action="">
  <!-- name -->
  <label for="name">Name</label>
  <input type="text" name="name" id="name">
  <br>
  <br>
  <!-- email -->
  <label for="email">Email</label>
  <input type="text" name="email" id="email">
  <br>
  <br>
  <!-- description -->
  <p>Description</p>
  <textarea name="description" id="" cols="30" rows="10" placeholder="Your Description"></textarea>
  </form>
  <br>
 <br>
 <br>
 <br>
 <br>
 <p>copyright&copy;2021</p>
 <h3><a href="#logo">Back To Top</a></h3>
</body>

</html>

Et le résultat du formulaie

../_images/Capture74.PNG

On constate que l’attribut action=”” reste vide car pour l’instant nous n’allons pas envoyer les données ailleurs.

css

https://github.com/amycesal/dataviz-style-guide/blob/master/Sunlight-StyleGuide-DataViz.pdf

Il y trois façon de travailler avec css :

  • inline css

  • internal css

  • external css

inline css

Pour le inline dans la balise on écrira l’attribut style=””

../_images/Capture110.PNG ../_images/Capture210.PNG

Ajoutons un autre attribut qui est font-size, ne pas oublier de séparer les attributs par un point virgule.

../_images/Capture310.PNG ../_images/Capture45.PNG

Le désavantage de travailler en inline est que pour chaque élément nous devrons créer un style. Si par exemple nous aurions 500 x h1 alors pour tout changer cela risque de prendre longtemps. Donc le inline styling est quelque chose de très basique.

Internal css

Pour le internal css, on va mettre entre les tags heads un tag style est décrire le style de tous nos éléments par exemple si l’on veut pour l’élément h1 une couleur blue et un font-size de 3rem et un autre style pour h2 on écrira la chose de la manière suivante:

../_images/Capture510.PNG ../_images/Capture610.PNG

avec cette méthode il sera facile de modifier la couleur de tous les h1 en entrant simplement la couleur désirée à un seul endroit. Ceci va marcher uniquement pour la page où est déclaré style. Admettons qu’il y a 10 pages html. Il faudrait alors dans chaque page insérer style. Au moindre changement de style, il faudra passer au travers de tous les fichiers pour modifié le style donc beaucoup de temps d’édition. Une autre solution consistera a faire un fichier avec une extension .css qui engloberait tous les styles pour toutes les pages. En en vient alors à external css.

External css

Pour ce faire il faut créer un fichier dans le projet nommé xxx.css xxx n’est pas bien important du moment où il y l’extension .css. La convention toutefois est de préciser le nom à style donc un style.css

../_images/Capture75.PNG

Pour dire à nos fichiers html d’utiliser ce fichier css, on indiquera dans les fichiers entre les tags head,

../_images/Capture81.PNG

Remarque: En général, le fichier styles.css doit ce mettre dans un répertoire nommé css. Nous devons donc modifié le path (ou chemin) de notre fichier.

../_images/Capture91.PNG ../_images/Capture101.PNG

Priorités entre external/internal/inline css

L’inline vient en première priorité, ensuite internal et l’external vient en dernière priorité.

Commentaires

Se qui vient entre /* et */ est considéré comme un commentaire.

Noms des éléments dans le css

  • selector c’est par exemple h1, h3

  • property c’est par exemple color, font-size

  • value c’est par exemple orange, 4rem

Exemple de fichier styles.css

Créons d’abord un fichier index.html avec h1, h2, et p sur lequel nous allons appliqué différent style avec le fichier styles.css

../_images/Capture112.PNG

Le fichier styles.css

../_images/Capture122.PNG

Le résultat

../_images/Capture132.PNG

Comment faire si l’on veut que tout le texte soit en bleu?

../_images/Capture141.PNG

Grouping Selectors

Comment dire que tout soit en rouge sauf h1 et h2 en bleu?

on utilisera le grouping selectors

../_images/Capture151.PNG

Remarquer que les différents selectors sont séparés d’une virgule.

ID selectors

Permet d’appliqé différents style sur le même selector

../_images/Capture161.PNG

Exemple

Comment peut-on faire si l’on veut appliqué des styles différents à h1 Title heading et à h1 Footer Heading?

On utilisera l’attribut id dans le fichier html à l’intérieur du tag et un dièse avec le nom de l’id dans le fichier styles.css

Fichier index.html

../_images/Capture171.PNG

Fichier styles.css

../_images/Capture181.PNG

Résultat

../_images/Capture191.PNG

Class selectors

Exemple:

../_images/Capture201.PNG ../_images/Capture212.PNG ../_images/Capture222.PNG

Nous aurions pu utiliser id selector, mais nous aurions du faire un id différents pour chaque h3 différents. L’id doit être unique.

Combinaison entre id et class selector

../_images/Capture232.PNG ../_images/Capture241.PNG ../_images/Capture251.PNG

Remarquez quand on on écrit class=”green lowercase” c’est en fait deux class différentes séparée par un espace.

div span

Prenons un exemple un titre suivi d’un paragraphe, et un deuxième titre suivi d’un deuxième paragraph. A l’intérieur du deuxième paragraph mettons “hey i’m uppercase” à deux endroit différent.

../_images/Capture261.PNG

Maintenant nous voudrions avoir le premier titre et le premier paragraphe en rouge. Le second titre et le second paragraphe en bleu.

Pour ce faire nous ne pouvons sélectionner h3 ni p car nous aurions les deux de la même couleur. Bien sûr nous pourrions utiliser id, mais il existe une meilleures solution. L’utilisation de div et de span pour grouper.

On va donc faire un premier groupe ou bloc avec div en le mettant avant le premier h3 et le deuxième tag du div à la fin du premier paragraphe.

../_images/Capture271.PNG

En mettant ce div rien ne change à l’affichage. Nous allons faire de même pour notre texte que l’on veut afficher en uppercase, mais cette fois nous allons utiliser span pour grouper notre texte.

../_images/Capture281.PNG

Dans notre css mettons un selector div et un span

../_images/Capture291.PNG ../_images/Capture301.PNG

Donc le div est utilisé pour créer un bloc et span est utilisé pour du inline. Un div créera un espace après lui, mais pas span.

Pour mettre une autre couleur à notre deuxième titre et deuxième paragraphe, nous allons utilisé nos class dans les div.

Supprimer dans le styles.css le selector div. et mettons les class appropriées dans les div du fichier index.html

../_images/Capture312.PNG ../_images/Capture322.PNG

Nous pouvons aussi utiliser une class pour span. Par exemple, si nous voulons mettre une class red à notre premier span

../_images/Capture332.PNG ../_images/Capture341.PNG

Inheritance

Tous les éléments enfants hérite du style des style appliqué aux parents. Prenons un exemple de deux paragraphes.

../_images/Capture351.PNG

Mettons un selector body avec color à red.

../_images/Capture361.PNG

Les deux paragraphes seront de couleur rouge. Car les paragraphes sont à l’intérieur de body et sont donc enfant de body. Body est le parent de paragraphe. Dans ce cas on dira que p à hérité des styles de body.

Maintenant mettant les deux paragraphes à l’intérieur de div

../_images/Capture371.PNG ../_images/Capture381.PNG

Maintenant les deux paragraphes sont blue. Pourquoi ceci est comme cela car div est l’enfant de body. C’est parce que div reçu un style spécifique, le style de body ne compte plus. Les deux paragraphes ont hérité du style de div.

Si l’on ajoute un h2 dans le div et un selector h2 dans le styles.css, alors h2 les styles appliqués sur h2 sera prioritaire. Dans ce cas h2, aura une couleur verte qui prime sur le rouge de body, mais héritera quand même le uppercase de body.

../_images/Capture391.PNG ../_images/Capture401.PNG ../_images/Capture412.PNG

Il y a quelques proprety de parent qui ne vont pas être hérités par les enfants. Dans l’exemple suivant, div possède un proprety border on voit que cette property n’est appliquée qu’au div.

../_images/Capture421.PNG

Last Rule and Specificity Universal Selector

Il arrive lorsque le fichier styles.css devienne très grand et sans faire exprès, nous déclarons un selector plusieurs fois. Le dernier déclaré dans le fichier sera pris en considération.

Admettons maintenant que nous avons pour le div une couleur verte déclacrée après avoir déclaré h2. Bien que div soit déclaré après la couleur de notre h2 reste verte. Il y a donc un spécificité dans les sectors qui prennent les propriétés avant les selectors placé après.

Pour plus d’information sur ce sujet, on peut trouver dans google en tapant “specificity measurement css”. Ou sur 3schools.com

../_images/Capture431.PNG

Il existe des selectors universels comme par exemple * qui sélectionnera tous les selectors, mais ne sera pas prioritaire sur certain selector positionné en fin de liste.

color properties / color background-color

  • color property est responsable de la couleur du texte

  • background-color est responsable de la couleur du fond de texte

Exemple :

../_images/Capture441.PNG ../_images/Capture451.PNG ../_images/Capture461.PNG

comme on peut le constater, l’utilisation de backround-color et background produise le même résultat.

L’utilisation la plus commune est d’utiliser les couleurs par leur nom. Visual Studio propose directement les noms existants des couleurs. Il y 140 nom de couleurs.

RGB

Il y a un autre moyen d’indiquer la couleur qui l’utilisation de rgb qui signifie red green blue, chaque couleur va de 0-255 0 étant le noir

../_images/Capture471.PNG ../_images/Capture481.PNG

Une valeur 255 pour r représente la couleur pour rouge, 255 pour le g représente la couleur verte, 255 pour le b représente la couleur bleu. rgba ^^^^

La lettre a est pour opacité / transparence. (de 0 à 1)

../_images/Capture491.PNG ../_images/Capture501.PNG

On voit que plus la valeur de a tend vers 0 est plus le fond devient transparent.

hex value

#RRGGBB

Au lieu d’avoir des valeurs variant de 0 à 255 on aura des valeurs de 0 à F (hexadecimal) après 9 vient A

Visual Studio permet de se déplacer dans la zone pour choisir notre couleur et l’opacité avec le premier ascenseur à gauche. Et de convertire entre les différents code couleurs (rgb, hex, hsl)

../_images/Capture511.PNG

Choisir sa palette de couleur

Il y a un site https://coolors.co il faut appuyer sur space pour changer de couleur et sur le cadenas pour choisir la couleur.

font-size, width, height, pixels

  • font-size est pour ajuster la taille du texte

  • width et height contrôle respectivement la largeur et la hauteur d’un élément (h1, …)

  • pixel est une unité absolue comme le plus petit point d’un écran pourquoi absolue? c’est parce que si on modifie la fenêtre du browser la mesure sera toujours identique.

../_images/Capture521.PNG ../_images/Capture531.PNG

Quand est-il avec height?

../_images/Capture541.PNG ../_images/Capture551.PNG

Percent value / relatives

../_images/Capture561.PNG ../_images/Capture571.PNG

On voit que la zone rouge est 50% plus petite en largeur et en hauteur par rapport à la partie bleu qui est l’élément parent du div en rouge..

em relative

Par défaut, la taille du texte dans une fenêtre d’un browser est de 16px.

../_images/Capture581.PNG ../_images/Capture591.PNG ../_images/Capture601.PNG

On voit que la taille des deux textes sont identiques car une fait 32px et comme 1em fait par défaut 16px donc 2x16=32px

Changeons maintenant la taille dans le browser à très grand, donc on modifie la taille par défaut de 16px à plus grand. 1em sera plus grand que 16px et apparaîtra plus grand que le texte absolute

../_images/Capture612.PNG ../_images/Capture621.PNG

Créons des div qui sont des parents à nos h3

../_images/Capture631.PNG ../_images/Capture641.PNG

et mettons div selector un font-size de10px

../_images/Capture651.PNG

On voit que relative est devenu plus petit car font-size de parent est devenu plus petit que 16px. Le texte absolute n’a pas changer.

rem

Contrairement à em, rem ne dépend pas du parent, mais de root. Le root est le tag html.

Dans l’exemple précédent si l’on met à la place de em, rem,

../_images/Capture661.PNG

la taille n’héritera pas du parent qui est 16px dans ce cas là (defaut du browser). Par contre, si on le mais dans le root,

../_images/Capture661.PNG

la taille du texte relative changera.

../_images/Capture671.PNG

vh - height / vw - width (percent of the screen)

Ce sont des unités relatives par rapport à la taille de l’écran (fenêtre).

../_images/Capture681.PNG

on mettra vw pour width et vh por height.

../_images/Capture691.PNG ../_images/Capture701.PNG

On voit que le carré rouge fait exactement la moitié de la fenête que se soit en hauteur ou en largeur. (ne pas prendre en compte la petite marge) Ces valeurs sont souvent utiliser pour les banners. (entête)

Default browser styles and google devTools

Pour ouvrir le devTool, faire un clique droite sur le browser et choisir inspecter. Il est vrai que c’est assez intimidant au début. Pour l’instant nous allons uniquement utiliser le menu Element. On retrouve tous les éléments que notre page possède (head, metatag, body, h1…)

Que se passe-t-il lorsque l’on clique sur h1?

../_images/Capture712.PNG

Nous retrouvons notre css syntaxe. (voir element.style {}). Mais nous voyons des autres informations que l’on a pas entrée. Comme par exemple dispay: block; font-size: 2em; En fait ce sont les styles que chaque browser applique par défaut.

../_images/Capture721.PNG

On remarque user agent stylesheet, cet inscription signal que ce sont les styles du browser appliqués par défaut. On peut réécrire ces valeurs comme par exemple la modification des marges.

Rajoutons un h2 est mettons quelques styles

../_images/Capture731.PNG ../_images/Capture741.PNG ../_images/Capture751.PNG

Le devTool nous indique notre fichier styles.css et en dessous qu’elle propriété ne sont plus celle par défaut (biffé) Ce que l’on peut faire aussi c’est modifié directement dans le devTool des valeurs. Le fichier d’origine ne sera pas modifié.

Calc

Permet de faire des opérations mathématiques comme addition, soustraction, multiplication, division.

../_images/Capture76.PNG ../_images/Capture77.PNG ../_images/Capture78.PNG

On remarque que la page est plus grande que ce que l’écran peut afficher contre le bas. Le dépassement est égale à 100px (la hauteur de navbar) Pour corriger cela on corrigera la hauteur en utilisant calc

../_images/Capture79.PNG

Cette méthode est souvent utilisée pour la page d’accueil quand il y a une barre de navigation est le banner en dessous. Attention de bien mettre un espace avan et après l’opération (ici le - )

font-size font-family

Permet de changer la police d’écriture pour chaque élément que l’on veut.

../_images/Capture80.PNG ../_images/Capture811.PNG ../_images/Capture82.PNG

font-stack generic-family

Il se peut que les polices que l’on a choisie ne soient supportées par le browser. Visual Code nous propose une série de font qui se ressemble séparée d’une virgule.

../_images/Capture83.PNG

Google Fonts

Google propose aussi des fonts que l’on peut incorporer.

font-weight

Si l’on veut mettre en gras.

font-style

Pour mettre en italic, oblique, normal.

text-align

../_images/Capture84.PNG ../_images/Capture85.PNG

On peut utiliser left qui est par défaut à gauche et right pour droite.

text-indent

Sert à indenter la première ligne d’un paragraphe.

line-height letter-spacing word-spacing text-transform text-decoration

../_images/Capture88.PNG ../_images/Capture89.PNG ../_images/Capture90.PNG

CSS Box Model

../_images/Capture911.PNG

Padding

../_images/Capture92.PNG ../_images/Capture93.PNG ../_images/Capture94.PNG

Les paddings appliqués sur le p, sont des raccourcis.

Margin

Est la marge entre le bord de l’écran et l’élément.

Warning

Les browsers applique par défaut une marges. C’est souvent source de confusion.

Tout comme le padding, on peut utiliser les raccourcis.

../_images/Capture95.PNG ../_images/Capture96.PNG

Comment faire pour coller ici le carré rouge au carré bleu?

../_images/Capture97.PNG ../_images/Capture98.PNG

Si l’on veut mettre tous les marges à 0 on écrira :

margin:0;

On retrouvera les mêmes raccourcis que padding. C’est-à-dire margin: 20px (1 valeur) appliquera 20px sur les quatre côtés. Avec 2 valeurs alors la première valeur représentera le top et le bottom la deuxième et pour la marge de droite et de gauche. On peut spécifier avec 4 valeurs qui sont respectivement pour le top, droite, bas, et gauche.

Border

Pour encadrer les éléments.

../_images/Capture99.PNG ../_images/Capture100.PNG

Il y a aussi des raccourcis pour borer. L’ordre des valeurs est pas importante.

../_images/Capture1011.PNG ../_images/Capture102.PNG

On peut aussi choisir qu’un seul coté avec par exemple, border-bottom pour le coté du bas.

Arrondir et margin négatif

Pour un placement qui doivent se chevaucher, utiliser un margin négatif. Les coins peuvent aussi être arrondi grâce à la commande border-radius.

../_images/Capture103.PNG ../_images/Capture104.PNG

outline

est utilisé pour déplacer le cadre vers l’extérieur ou vers l’intérieur à l’aide de outline-offset suivant qu’il est positif ou négatif.

../_images/Capture105.PNG ../_images/Capture106.PNG

Display

  • Block crée toujours une ligne d’espacement

  • Inline ne crée pas de ligne d’espacement et sa taille s’ajuste au contenu.

On remarque que block s’étend sur toute la largeur de la page.

../_images/Capture107.PNG ../_images/Capture109.PNG ../_images/Capture108.PNG

Certains éléments possèdent leur propre display property.

Avec la propriété display on peut changer le display qui est réglé par défaut.

../_images/Capture1101.PNG ../_images/Capture1111.PNG

Horizontal Centering

../_images/Capture1121.PNG ../_images/Capture113.PNG

Pour aligner les blocks en bleu, nous devons écrire cela comme ceci

L’utilisation de margin est nécessaire ici 25px est la marges du haut et du bas tandis ce que auto est la marge automatique qui centre le block.

../_images/Capture114.PNG ../_images/Capture115.PNG

Top Bottom Margin

  • Block: Top Bottom Margin Respected

  • Inline: Top Bottom Margin Not Respected

Mobile Navbar

Nous voyons que pour le div c’est un block donc les marges du haut et du bas peuvent être modifiées.

../_images/Capture118.PNG ../_images/Capture116.PNG ../_images/Capture117.PNG

Enlevons ce bloc et créons notre Navbar

../_images/Capture119.PNG ../_images/Capture120.PNG

Faisons notre fichier styles.css

Enlevons d’abord toutes les marges

../_images/Capture1211.PNG ../_images/Capture1221.PNG

Mettons un font-family sur le body

List-style-type:property

pour sélectionné un enfant on écrira ul li{...} et pour changer le point de list on utilsera list-style-type

../_images/Capture123.PNG ../_images/Capture124.PNG

Pour notre Navbar, nous ne voulons pas de point, on les supprime avec none.

../_images/Capture125.PNG ../_images/Capture126.PNG

descendant selectors

ul li a est la sélection la plus précise qui va jusqu’à l’élément a. ici li ne sera pas sélectionnée.

../_images/Capture127.PNG
  1. Enlevons la décoration du texte (le souligné)

  2. Transformons le texte en capitalisant

  3. Mettant de l’espace entre les lettres

  4. Background à 222

  5. color à f15025

    ../_images/Capture128.PNG ../_images/Capture129.PNG
  6. espaçons un peu les lignes

    ../_images/Capture130.PNG

    voilà le résultat, le padding est bien mais les lignes restent serrées.

    ../_images/Capture1311.PNG
  7. essayons de mettre du marging

    ../_images/Capture1321.PNG ../_images/Capture133.PNG

    Le menu s’est déplacé un peu à droite mais les marges haut et bas n’ont pas été appliquées. On se rappelle les marges haut et bas ne sont pas appliquée aux éléments inlines comme ici un li un élément d’une liste.

  8. ok, enlevons d’abord padding et margin et mettons un display: block

    ../_images/Capture134.PNG ../_images/Capture135.PNG

    On voit que c’est devenu un block car il occupe toute la largeur de la page.

  9. Rajoutons padding

    ../_images/Capture136.PNG ../_images/Capture137.PNG
  10. Si nous rajoutons margin la marge est crée

    ../_images/Capture138.PNG ../_images/Capture139.PNG
  11. Enlevons margin car cela était juste pour montrer que le top et bottom margin était appliqué

Inline-Block

../_images/Capture140.PNG ../_images/Capture1411.PNG

faisons le fichier css

../_images/Capture142.PNG ../_images/Capture143.PNG

on voit que margin n’a fonctionner que pour la droite et la gauche le top et le bottom n’a pas bougé. C’est parce qu’on est en inline. On peut essayer de mettre le display à block et voir si on peut régler le top et bottom.

../_images/Capture144.PNG ../_images/Capture145.PNG

Mais cela n’arrange pas les choses. On n’aimerait avoir tout sur une ligne et pouvoir réglé margin top et bottom.

En utilisant inline-block margin top et bottom fonctionne.

../_images/Capture146.PNG ../_images/Capture147.PNG

box-sizing

../_images/Capture148.PNG ../_images/Capture154.PNG ../_images/Capture149.PNG

Ajoutons un padding à la box-1

../_images/Capture150.PNG ../_images/Capture1511.PNG

On remarque que la box-1 a c’est agrandie de 20px de chaque coté. Mettons aussin un padding à box-3

../_images/Capture152.PNG ../_images/Capture153.PNG

Ouvrons le devTool de chrome et inspectons box-1, on voit que la dimensions est passée à 240px par 240px.

../_images/Capture155.PNG

Le padding est souvent source de confusion car il augmente la taille des éléments.

C’est là qu’intervient le box-sizing: border-box

../_images/Capture156.PNG ../_images/Capture157.PNG

Si l’on inspecte à nouveau le devTool

../_images/Capture158.PNG

on voit que l’intérieur est passé à 160x160px donc il n’a pas agrandi le div, mais à déplacé le texte de 20px de chaque coté vers l’intérieur du div.

display:none opacity:0 visibility:hidden

../_images/Capture159.PNG ../_images/Capture160.PNG

display:0

../_images/Capture1611.PNG ../_images/Capture162.PNG ../_images/Capture163.PNG ../_images/Capture164.PNG ../_images/Capture165.PNG ../_images/Capture166.PNG

En ouvrant le devTool, on constate que display à none est complètement caché, par contre opacity:0 et visibility:hidden l’élément reste présent dans le devTool.

Background images

Pour ce faire piquons sur pexels trois images que l’on va renommer par big.jpg small.jpg et folder-img.jpg. Redimensionnons big.jpg et folder-img.jpg à 400px de haut, small.jpg à 100x100px avec Gimp.

Disons que le div n’a pas de limite de largeur, mais une hauteur limitée à 400px. et mettons une couleur rouge pour le texte.

../_images/Capture167.PNG ../_images/Capture168.PNG ../_images/Capture169.PNG

Pour le placement de l’image nous allons utiliser background: mais cette fois ci pas comme nous avons l’habitude de mettre color, à la place nous allons mettre un url().

path image

pour le path de l’image, uniquement cette notation fonctionne pour moi pour voir directement dans le chrome en ouvrant index.html (sans live server) : url("../big.jpg"). Si le l’image est dans un dossier nommé img url("../img/big.jpg")

../_images/Capture170.PNG ../_images/Capture1711.PNG ../_images/Capture172.PNG

On voit que lorsque l’on agrandi la fenêtre, si elle devient plus large que l’image alors le browser dupliquera l’image à droite.

../_images/Capture173.PNG ../_images/Capture174.PNG

Le browser par défaut a remplir tout le div par les images en les dupliquant non seulement en largeur mais aussi en hauteur.

../_images/Capture175.PNG ../_images/Capture176.PNG

Background-repeat

backround-repeat: repeat; rien ne change car c’est la valeur par

défaut.

backround-repeat: no-repeat;

../_images/Capture177.PNG ../_images/Capture178.PNG

On voit qu’une image car nous avons réglé à no-repeat.

background-repeat: repeat-x ou repeat-y

../_images/Capture179.PNG ../_images/Capture180.PNG

Pour répéter l’image en largeur seulement. Mettre repeat-y pour répéter l’image en hauteur.

background-repeat: space

../_images/Capture1811.PNG ../_images/Capture182.PNG

On distingue de l’espace entre les images répétées.

background-repeat: round permet affichera toujours une image dans toute sa largeur. Attention, elle sera déformée.

../_images/Capture183.PNG ../_images/Capture184.PNG

Pour ce qui est le plus couramment utilisé c’est le background-repeat: no-repeat

Background-size: cover

Etend l’image sur toute la largeur du div quelque que soit la taille de l’image. L’image ne sera pas déformée. Il faudra faire attention à bien dimensionné l’image avant pour que l’image ne soit pas trop pixelisée en étendant le div.

../_images/Capture185.PNG ../_images/Capture186.PNG

Background-size: contain

../_images/Capture187.PNG ../_images/Capture188.PNG

Ne modifie pas le ratio de l’image.

Note

De tous ces background, celui qui sera le plus utilisé sera le cover pour faire des nices banners.

Background-position

../_images/Capture189.PNG ../_images/Capture190.PNG

La petite image est centrée.

Note

Ecrire right bottom est tout à fait possible.

../_images/Capture1911.PNG ../_images/Capture192.PNG

Utile si l’on veut voir plûtot le bas, le haut le centre, ou droite ou gauche de l’image quand on agrandi l’image. Ici on se penche plutôt pour le bas.

Pour un positionnement encore plus précis on écrire en %.

../_images/Capture193.PNG ../_images/Capture194.PNG

Le premier % représente l’horizontal, et le deuxième, la verticale.

Background-attachment

Ajustons d’abord le div:

../_images/Capture195.PNG ../_images/Capture196.PNG

La hauteur de l’image est égale à la fenêtre.

et mettons le texte au centre et enlevons le margin par défaut avec *{}

../_images/Capture197.PNG ../_images/Capture198.PNG

Apportons encore quelques modifications

../_images/Capture199.PNG

Cette configuration peut-être utilisée pour les images d’arrière-plan d’un site internet.

Mettons maintenant un background-attachement

../_images/Capture200.PNG

Qui a fixé l’image, pendant que l’on scroll vers le bas, le texte sur le dessus de l’image bouge.

Gradients

../_images/Capture2011.PNG ../_images/Capture202.PNG ../_images/Capture203.PNG

Sur une image

../_images/Capture204.PNG ../_images/Capture205.PNG ../_images/Capture206.PNG ../_images/Capture207.PNG ../_images/Capture208.PNG ../_images/Capture209.PNG

Pour l’instant, on remarque qu’il n’y a pas de dégradé, changeons le paramètre a = 0.1

../_images/Capture2101.PNG

On distingue maintenant le gradué :

../_images/Capture2111.PNG

Associons une image. Attention de ne pas oublier la virgule.

../_images/Capture2121.PNG ../_images/Capture213.PNG

On voit que l’image s’est assombrie, on peut très bien prendre une autre couleur aussi.

Utilisation de raccourci pour background
../_images/Capture214.PNG ../_images/Capture215.PNG

Note

Attention, no-repeat et fixed ne peuvent être permuter.

Cela évite de tapez background… sur plusieurs lignes. L’image à la même propriété que la première sauf qu’il y a plus de dégradé. (idéal pour lire du texte sur l’image)

Linear gradient generator

Il existe un site https://www.colorzilla.com/gradient-editor/ qui permet de générer les dégradés. Ensuite il faut copier le code css.

../_images/Capture216.PNG ../_images/Capture217.PNG ../_images/Capture218.PNG

Float property

../_images/Capture219.PNG ../_images/Capture220.PNG ../_images/Capture2211.PNG ../_images/Capture2221.PNG

On voit que le paragraphe est mis en-dessous de l’image car c’est un last block element.

Mettons maintenant un border et un padding

../_images/Capture223.PNG ../_images/Capture224.PNG

Que se passe-t-il maintenant si l’on utilise la propriété float?

On est tenté de dire que l’image est déjà floated vers la gauche. Mais par défaut la propriété est à none. Mettons float à left.

../_images/Capture225.PNG ../_images/Capture226.PNG

Si l’on met un left alors l’élément suivant va ête aussi à left, comme dans ce cas. Si l’on veut mettre l’élément suivant comme normal, il faudra utiliser la propriété clear: left.

../_images/Capture227.PNG ../_images/Capture228.PNG

Faisons la même chose avec right:

../_images/Capture229.PNG ../_images/Capture230.PNG

Rajoutons une deuxième image

../_images/Capture2311.PNG ../_images/Capture2321.PNG

En utilisant clear: both, le paragraphe revient à la ligne normal. C’est comme si on lui aurait enlevé la propriété left ou right.

../_images/Capture233.PNG ../_images/Capture234.PNG

L’image sort du div, en utilisant la commande overflow: hidden, on coupe la partie qui dépasse.

../_images/Capture235.PNG ../_images/Capture236.PNG

Enlevons une image et mettons l’image à droite du paragraphe.

../_images/Capture237.PNG ../_images/Capture238.PNG

On peut facilement mettre un peu de marge

../_images/Capture239.PNG ../_images/Capture240.PNG

Un autre exemple avec float

../_images/Capture2411.PNG ../_images/Capture242.PNG ../_images/Capture243.PNG

Si l’on rajoute un h1

../_images/Capture244.PNG ../_images/Capture245.PNG

On croirait que tout va bien le h1 c’est bien mis sur une nouvelle ligne.

Mais rajoutons un div

../_images/Capture246.PNG ../_images/Capture247.PNG

On voit que le hello world ne sait pas mis sur une nouvelle ligne.

Pour mettre le h1 comme il devrait s’afficher (sur une nouvelle ligne) on fera appel à clear:both.

../_images/Capture248.PNG ../_images/Capture249.PNG

c’est une bonne habitude de mettre ce clear:both pour des raisons de déboggage qui pourraient s’avérer pénible.

position: relative

avec position: relative, 4 options permettent de déplacer l’élément soient, top, bottom, left, right. Ils déplacent l’élément par rapport au flux normal (position normale par défaut)

../_images/Capture250.PNG ../_images/Capture252.PNG ../_images/Capture2511.PNG ../_images/Capture253.PNG ../_images/Capture254.PNG ../_images/Capture255.PNG ../_images/Capture256.PNG ../_images/Capture257.PNG ../_images/Capture258.PNG ../_images/Capture259.PNG ../_images/Capture260.PNG

position: absolute

C’est la rock-star du css.

../_images/Capture2611.PNG ../_images/Capture262.PNG

Si l’élément d’avant est positionné avec relativ alors cet élément sera la référence pour l’élément positionné avec absolute. Pour voir mettons l’élément d’avant ici .two avec relative.

../_images/Capture263.PNG ../_images/Capture264.PNG

Enlevons-là pour voir

../_images/Capture265.PNG ../_images/Capture266.PNG

On voit que la référence est devenu le body.

Mettons la position du div à relative

../_images/Capture267.PNG ../_images/Capture268.PNG

Pour le mettre à la moitié du body, on enlève le relative de .div

../_images/Capture269.PNG ../_images/Capture270.PNG

position: fixed

Cet propriété sert à fixer un bouton par exemple pour qu’il soit fixe lorsque l’on scroll en-bas de la page.

../_images/Capture2711.PNG ../_images/Capture272.PNG

Media Queries

Est utilisé pour appliquer différents styles suivant la grandeur de l’écran. En général on commence par l’écran le plus petit vers le plus grand.

../_images/Capture273.PNG ../_images/Capture274.PNG

Attention au un simple oubli d’un espace est la syntaxe est fausse.

min-width

../_images/Capture275.PNG ../_images/Capture276.PNG

la syntaxe min-width indique à partir de quelle grandeur le style doit être appliqué.

On peut utiliser le devTool pour inspecter la grandeur de l’écran.

../_images/Capture277.PNG ../_images/Capture278.PNG

Si nous n’écrasons pas dans @media un style déjà défini, comme par exemple text-decoration: underline, ce style sera maintenu.

Dans l’exemple suivant, on va mettre deux seuils pour avoir en fait trois styles différents.

../_images/Capture279.PNG ../_images/Capture280.PNG

On observe que dès que la fenêtre dépasse 768px alors le style vert est appliqué.

max-width

max-width indique que jusqu’à max-width le style est appliqué. Au-delà un autre style est appliqué.

../_images/Capture2811.PNG ../_images/Capture282.PNG ../_images/Capture283.PNG

Ce que l’on doit faire attention c’est que l’on peut écraser facilement les styles. Ici 768px écrase le 576px car il inclu ce dernier. Donc le style rouge (576px) ne sera jamais utilisé. Par contre si un style declaré dans 576px et ne figure pas dans 768px alors celui-ci sera tout de même appliqué.

../_images/Capture284.PNG ../_images/Capture285.PNG

z-index

Avec z-index, on peut règler l’ordre de juxtaposition des images.

Nous voulons comme ancêtre pour banner position: relative.

On distingue que les images sont superposées. Dans l’ordre dans lequelle elle ont été déclarées.

../_images/Capture286.PNG ../_images/Capture287.PNG

Par défaut, les images ont un z-index égale 0.

Si l’on met pour la première image un z-index égale à 0 l’image reste comme elle était.

../_images/Capture288.PNG ../_images/Capture289.PNG

Mettons z-index à 1 et l’image passe devant les autres.

../_images/Capture290.PNG ../_images/Capture2911.PNG

Passons des z-index au trois, afin que la troisième image passe en arrière, ensuite la deuxième et la première en avant.

../_images/Capture292.PNG ../_images/Capture293.PNG

on peut très bien mette un z-index de -999 c’est la grandeur qui fait la priorité.

z-index fonctionne seulement en absolute et en relative. Si l’on met static alors z-index ne fonctionnera pas.

../_images/Capture294.PNG ../_images/Capture295.PNG

Dans ce cas tout fonctionne normalement. Si l’on met un z-index à 100, alors rien ne se passe avec position static. (le .one devrait passer tout en avant)

../_images/Capture296.PNG ../_images/Capture297.PNG

Pour que cela fonctionne il faut mettre à relative ou aboslute

../_images/Capture298.PNG ../_images/Capture299.PNG

pseudo elements ::before ::after CONTENT

::before

Pour l’exemple suivant nous allons créer un simple paragraphe.

../_images/Capture305.PNG ../_images/Capture300.PNG ../_images/Capture3011.PNG

On voit que le mot hello s’est collé devant le contenu de notre paragraphe écrit en html.

On peut rajouter n’importe quelle propriété

../_images/Capture303.PNG ../_images/Capture304.PNG

Si l’on ouvre le devTool on peut voir que le ::before a été rajouter dans le p

../_images/Capture306.PNG

::after

Ceci est rajouter inline.

On peut changer en block

../_images/Capture307.PNG ../_images/Capture308.PNG

Donc nous avons nos sudo éléments avant et après le paragraphe.

content doit toujours être renseigné

../_images/Capture309.PNG ../_images/Capture3101.PNG ../_images/Capture3111.PNG ../_images/Capture3121.PNG

on doit donc quand même spécifié content:”” quand il n’y pas de texte.

Cas pratique avec ::before et ::after

Nous allons rajouter une image et ce qui est important c’est que img soit dans un div.

../_images/Capture313.PNG ../_images/Capture314.PNG

Changeons la largeur de l’image

../_images/Capture315.PNG ../_images/Capture316.PNG

ok, cela fonctionne, mais il y a une meilleure solution.

Nous allons modifier le div et l’image sera responsible à ce div.

../_images/Capture317.PNG ../_images/Capture318.PNG

On remarque que l’image ne s’intégre pas dans le div (cadre rouge)

Pour la faire entrer dans le cadre mettons width: 100%

../_images/Capture319.PNG ../_images/Capture320.PNG

Même en modifiant le div l’image sera toujours intégrée au div

../_images/Capture3211.PNG ../_images/Capture3221.PNG

On remarque toutefois un espace enter le bas de l’image et le cadre du bas. On est tenté à mettre un height: 100% mais rien a bougé. Pour parer à cet inconvénient, il faut mettre à img un display: block. Ceci n’a rien à voir avec ::before ::after sudo elements, mais l’association en div et img requiert img avec un display: block.

../_images/Capture323.PNG ../_images/Capture324.PNG

Maintenant mettant quelque chose avec ::before avant l’image.

../_images/Capture325.PNG ../_images/Capture326.PNG

On remarque que hello ne s’est pas mis avant l’image, ceci est dû au fait que img représente déjà le contnent.

Donc essayons avec div, on met content à “” avec un border

../_images/Capture327.PNG ../_images/Capture328.PNG

On voit un petit rectangle gris, essayons maintenant de l’agrandir:

../_images/Capture329.PNG

On voit qu’il a pas bougé.

Mais nous connaissons la propriété absolute.

../_images/Capture330.PNG ../_images/Capture3311.PNG

On voit que le cadre n’est pas encore bon.

On se rappelle que absolut regarde pour quoi? Il regarde pour l’ancestor ou il y a un relative. S’il ne trouve rien il prendrea le body. C’est pourquoi le cadre est si grand. Donc on regarde pour l’ancestor et dans ce cas c’est div et rajoute un positon relative.

../_images/Capture3321.PNG ../_images/Capture333.PNG

On peut dire que ce n’est pas vraiment 100% car il réside de l’espace (un tout petit peu). La raison à cela est dans le border-box. Mettons alors box-sizing: border-box. et le résultat est bon.

../_images/Capture334.PNG ../_images/Capture335.PNG

Ce qui est cool c’est qu’on peut utilisé relatvie avec l’ancestor. On peut utilisée des valeurs négatives. Ce qui va faire déplacer le cadre.

../_images/Capture336.PNG ../_images/Capture337.PNG

Pour faire passer le cadre en arrière plan on utilisera z-index: -2 Occupons nous de div::after, copions ce qu’il y a dans le before et passons le entre div::before et l’image.

../_images/Capture338.PNG ../_images/Capture339.PNG

transition

Voici un petit avant goût de ce que l’on peut faire avec hover et transition

../_images/Capture340.PNG ../_images/Capture3411.PNG

Dès que l’on le pointeur de la souris passe par-dessus l’image alors after et before vont se décaller à 0;

Basic Selectors

../_images/Capture342.PNG ../_images/Capture343.PNG

Mettons quelques style à #heading

../_images/Capture344.PNG ../_images/Capture345.PNG

On voit qu’il y spécificité car #heading supplante le *. On se rappelle que lorsque l’on utilise id alors dans le css il faudra mettre #, pour class on mettra un point. Mettons maintenant à class du style.

../_images/Capture346.PNG ../_images/Capture347.PNG

On va donc que grâce à la spécificité on peut régler les styles de chaque élément spécifique.

Descendant and Child Combinators

Children peuvent être Descendant, mais Descendant ne peut pas être Child. Prenons un example pour clarifier.

Si l’on veut sélectionner uniquement les h1 qui sont dans un div on écrira

Donc ici les deux h1 seront en rouge.

../_images/Capture348.PNG ../_images/Capture349.PNG ../_images/Capture350.PNG

direct child

On peut sélectionner le direct child par exemple div > h1 sera sélectionner uniquement si h1 est directement sous div (qu’il n’y a rien entre le div et le h1) C’est pourquoi uniqument le premier h1 est sélectionner car l’autre h1 est sous li ul.

../_images/Capture3511.PNG ../_images/Capture352.PNG

On n’est pas limité uniquemnt aux selectors, class fonctionnent aussi.

../_images/Capture353.PNG ../_images/Capture354.PNG

.header est plus spécifique car c’est une class

fonctionne aussi avec direct child

../_images/Capture355.PNG ../_images/Capture356.PNG

first-line ::first-letter

../_images/Capture356.PNG ../_images/Capture357.PNG ../_images/Capture358.PNG

hover

../_images/Capture359.PNG ../_images/Capture3611.PNG ../_images/Capture360.PNG

On voit que quand on passe dessus avec le pointeur de la souris que le texte s’agrandit. Mettons un hover sur .header et sur a.

../_images/Capture3611.PNG ../_images/Capture362.PNG

root element of the document

../_images/Capture369.PNG ../_images/Capture370.PNG ../_images/Capture3711.PNG ../_images/Capture372.PNG

root est utilisé par exemple pour agrandir le texte dont la taille a été fixée par rem. On remarque que par absolute le texte ne change pas malgré le changment de root à 150%. En fait par défaut 1rem = 16px.

../_images/Capture373.PNG ../_images/Capture374.PNG ../_images/Capture375.PNG

transform

translate

un valeur négative fera déplacer l’élément vers la gauche et un pourcentage fera déplacer d’un pourcentage de la taille de l’élément à déplacé. Une valeur négative fera monter l’élément. On peut aussi combiner les deux directions.

../_images/Capture376.PNG ../_images/Capture377.PNG ../_images/Capture378.PNG
scale
../_images/Capture379.PNG ../_images/Capture380.PNG
rotation
rotateX

rotationZ fait une rotation autours de l’axe Z et est égale à rotation tout courts.

../_images/Capture3811.PNG ../_images/Capture382.PNG
skew
../_images/Capture383.PNG ../_images/Capture384.PNG

transition

Une transition est un changement effectué pendant un certain temps.

../_images/Capture385.PNG

ce hover va faire changer la couleur de tous les div en faisant passer le pointeur de la souris sur les div.

On remarque que le changement de couleur est instantané, si l’on veut que ce changement s’opère pendant un certain temps on écrira

../_images/Capture386.PNG

les 4s sont le temps que mettra la couleur du fond à virer du bleu au coloral.

Mettons une autre propriété de border-radius et l’on observe dès que l’on passe dessus le rayon passe directement à un rond. Pour que l’effet de border-radius se fasse aussi progressivement on séparera la propriété d’une virgule.

../_images/Capture387.PNG

l’effet est effectué sur les deux propriétés avec un délai de 4s. Par contre si l’on veut un délai différent alors on écrira

../_images/Capture388.PNG

Là, 4s est pour background et 2s est pour border-radius.

transition-delay

est pour mettre un délai comme pour un relai temporisé à la fermeture.

On peut noter d’autre manière

ici le 3s seconde représente la durée de la transition et 2s la tempo.

../_images/Capture389.PNG

Si l’on veut appliquer à border-radius aussi

../_images/Capture390.PNG

si l’on veut appliquer à toutes les propriétés

../_images/Capture3911.PNG

transition-timing-function

  • ease et default sont les mêmes

  • linear la vitesse de déplacement et la même du début à la fin.

  • ease-in accèlère progressive

  • ease-out plein pot au début et ralentissement progressive

  • ease-in-out accélération et déssélération progressive.

../_images/Capture392.PNG ../_images/Capture393.PNG ../_images/Capture394.PNG

Animation

On a vu transition qui fait l’action de 0 à 100%, avec animation on peut faire varier à n’importe quel pourcentage.

../_images/Capture395.PNG ../_images/Capture396.PNG ../_images/Capture397.PNG

iteration est le nombre de fois que l’animation doit se dérouler.

short hand

On peut écrire tout sur une ligne ceci remplace ce qui est commenté.

../_images/Capture398.PNG
animation-fill-mode

Une fois que le nombre d’itération a été effectué, la modification reste à la dernière ici opacity sera à 0.5.

../_images/Capture399.PNG ../_images/Capture400.PNG

:root{}

définition de variable global

utile si il y beaucoup de variable qui se répètent comme par exemple color.

../_images/Capture402.PNG ../_images/Capture403.PNG ../_images/Capture404.PNG
En local

Créons une nouvelle variable à l’intérieur de div et appelons-la dans .main-text et essayons aussi de l’appeler dans .third-heading. Comme .third-heading n’est pas dans un div alors la color ne sera pas réglée à rouge. Par-contre .main-text est dans un div et la coleur est au rouge.

../_images/Capture405.PNG ../_images/Capture406.PNG

Font Awesome

Tapez dans google font awesome.

à dévelloper car pas le droit de télécharger. Essayer un autre jour…

text-shadow

../_images/Capture407.PNG ../_images/Capture408.PNG ../_images/Capture409.PNG
text-shadow generator

tapez dans google text-shadow generator.

../_images/Capture4121.PNG

Ensuite, il faut copier le code.

box-shadow

../_images/Capture410.PNG ../_images/Capture4111.PNG
box-shadow generator

Il y a aussi un box-shadow generator

tapez dans google box-shadow generator

../_images/Capture413.PNG ../_images/Capture414.PNG

semantic

sert à structurer correctement une page html.

dans google tapez semantic w3school

emmet

si on utilise pas visual studio on peut tapez dans google emmet.

h1.maclass.big.yellow donnera

../_images/Capture415.PNG

h1#main

h3#third.third

header.header.main

#box.box-1.box-2

div>ul>li*5

p{some texte}

ul>li*6{$}

../_images/Capture416.PNG

JAVA Script

Get the most recent file in a directory node (à tester)

function getNewestFile(dir, regexp) {
  var fs = require("fs"),
  path = require('path'),
  newest = null,
  files = fs.readdirSync(dir),
  one_matched = 0,
  i

  for (i = 0; i < files.length; i++) {

     if (regexp.test(files[i]) == false)
         continue
     else if (one_matched == 0) {
         newest = files[i];
         one_matched = 1;
         continue
     }

     f1_time = fs.statSync(path.join(dir, files[i])).mtime.getTime()
     f2_time = fs.statSync(path.join(dir, newest)).mtime.getTime()
     if (f1_time > f2_time)
         newest[i] = files[i]
 }

 if (newest != null)
     return (path.join(dir, newest))
 return null
}

Coté client

Pour développer un script, il faut utiliser Visual Studio et installer l’extension Live Server. Ensuite ouvrir le répertoire et clique droite sur le fichier index.html qui contient le script et open with live server.

Pour que la page se rafraichisse automatiquement dans le browser, il faut mettre dans Visual Studio Code un délais à 600ms à Autosave.

Sever Side

How to install node.js

Without amin rights :

https://medium.com/@github.gkarthiks/how-to-install-nodejs-and-npm-in-non-admin-access-windows-machines-102fd461b54c

install that so it doesn’t need to restart the sever always:

  • npm install -g nodemon

Then enter :

  • nodemon index.js

Classes

../_images/Capture1100.PNG ../_images/Capture2100.PNG

Nous retournera 4.

On peut réassigner des nouvelles valeurs :

../_images/Capture3100.PNG

Ici le résultat sera de 3.

On peut aussi déclarer des fonctions dans nos class :

../_images/Capture417.PNG ../_images/Capture512.PNG

qui retounera : Loud Noise et 3

On peut passer une variable d’entrée Meow :

../_images/Capture613.PNG

Le résultat : Meow et 3

On peut aussi créer des static function :

../_images/Capture710.PNG ../_images/Capture86.PNG

On peut alors accéder à la fonction sans passer par une variable (let)

La fonction get permet de traiter notre objet comme une propriété.

../_images/Capture910.PNG ../_images/Capture1010.PNG

voici le résultat :

../_images/Capture1110.PNG

Admettons maintenant que nous voulions appliqué notre class à d’autre animaux comme chien, souris et que ces animaux hérite la même classe.

../_images/Capture1210.PNG

Ici Animal est la classe parent et Cat la classe enfant Cat aura hérité toutes les propriétés de Animal et on aura mis une autre valeur par défault à sound (meow).

Importons la class Cat

../_images/Capture1310.PNG

et appelons cat.makeNoise()

Voici le résultat :

../_images/Capture1410.PNG

Faisons un cat.metaData:

../_images/Capture1510.PNG

Résultat :

../_images/Capture1610.PNG

Loading Data Using Fetch

source : https://www.youtube.com/watch?v=2LhoCfjm8R4&t=15506s

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Loading and Parsing CSV Data</title>
   </head>
  <body>
    <script>

      
      const fetchText = async (url) => {
        const response = await fetch(url);
        return await response.text();
      };
      
const csvUrl = 'https://gist.githubusercontent.com/windwaver/1d5d788cd934c4369210a7192ff581e4/raw/cssNamedColors.csv'
      
      fetchText(csvUrl).then(text => {
        console.log(text);
      });
      
    </script>
    
  </body>
</html>

Parsing CSV Data with D3

<!DOCTYPE html>
<html>
  <head>
    <title>Loading and Parsing CSV Data</title>
    <script src="https://unpkg.com/d3@6.6.0/dist/d3.min.js"></script>
    <style>
      pre {
      font-size: 7em;
      }</style>
   </head>
  <body>
    <pre id="message-container"></pre>   
    <script>
      const fetchText = async (url) => {
        const response = await fetch(url);
        return await response.text();
      };
      
const csvUrl = 'https://gist.githubusercontent.com/windwaver/1d5d788cd934c4369210a7192ff581e4/raw/cssNamedColors.csv'
      
      fetchText(csvUrl).then(text => {
        const data = d3.csvParse(text)
        let message = '';
        message = message + Math.round(text.length / 1024) + ' kB\n';
        message = message + data.length + ' rows\n';
        message = message + data.columns.length + ' columns';
        document.getElementById('message-container').textContent =message;
      });
      
    </script>
    
  </body>
</html>

simplier

<!DOCTYPE html>
<html>
  <head>
    <title>Loading and Parsing CSV Data</title>
    <script src="https://unpkg.com/d3@6.6.0/dist/d3.min.js"></script>
    <style>
      pre {
      font-size: 7em;
      }</style>
   </head>
  <body>
    <pre id="message-container"></pre>   
    <script>
      
      
			const csvUrl = 'https://gist.githubusercontent.com/windwaver/1d5d788cd934c4369210a7192ff581e4/raw/cssNamedColors.csv'
      
      d3.csv(csvUrl).then(data => {
        let message = '';
        message = message + Math.round(text.length / 1024) + ' kB\n';
        message = message + data.length + ' rows\n';
        message = message + data.columns.length + ' columns';
        document.getElementById('message-container').textContent =message;
      });

      // With fetch, async, and await.
      // const fetchText = async (url) => {
      //  const response = await fetch(url);
      //  return await response.text();
      // };
      // fetchText(csvUrl).then(text => {
      //  const data = d3.csvParse(text)
      //  let message = '';
      //  message = message + Math.round(text.length / 1024) + ' kB\n';
      //  message = message + data.length + ' rows\n';
      //  message = message + data.columns.length + ' columns';
      //  document.getElementById('message-container').textContent =message;
      });
      
    </script>
    
  </body>
</html>

Loading Data with React and D3

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Loading Data with React & D3</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
      pre {
        font-size: 7em;
      }
    </style>
    <script src="https://unpkg.com/react@16.9.0/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16.9.0/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/d3@5.11.0/dist/d3.min.js"></script>    
  </head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>

index.js

import React, { useState, useCallback, useEffect } from 'react';
import ReactDOM from 'react-dom';
import { csv } from 'd3';
import { message } from './message'

const csvUrl = 'https://gist.githubusercontent.com/windwaver/1d5d788cd934c4369210a7192ff581e4/raw/cssNamedColors.csv'

const App = () => {
  const [data, setData] = useState(null);

  useEffect(() => {
    csv(csvUrl).then(setData);
  },[]);  
  
  return <pre>{data ? message(data) : 'Loading...'}</pre>;
};

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);

message.js

export const message = data => {
  let message = '';
  message = message + Math.round(d3.csvFormat(data).length / 1024) + ' kB\n';
  message = message + data.length + ' rows\n';
  message = message + data.columns.length + ' columns';
  return message;
};

React

L’installation a réussi dans le répertoire xxxxx_y, dans le répertoire formation cela échoue. Déplacer le répertoir où l’on veut après.

Pour compiler tapez :

npm start

Pour nettoyer après installation rapide voir cette video :

https://www.youtube.com/watch?v=dMH1_YtUTSQ

Deploy react on c-panel

follow this blog : https://dev.to/crishanks/deploy-host-your-react-app-with-cpanel-in-under-5-minutes-4mf6

Fichiers de base

Il faut au minimum un fichier index.html et index.js.

Contenu du fichier index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="style.css" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

Contenu du fichier index.js :

import React from "react"
import ReactDOM from "react-dom"

ReactDOM.render(<h1>Hello World</h1>, document.getElementById("root"))

on remarque la ligne

React from "react"

qui est là pour activer JSX, une combinaison entre html et js.

<h1>Hello world!</h1>

est écrit en JSX.

Si l’on veut mettre plusieurs balise html comme

<h1>Hello world!</h1><p>Ceci est un paragraphe</p>

nous devrons les inclure dans un un div

<div><h1>Hello world!</h1><p>Ceci est un paragraphe</p></div>

Ce tutoriel est basé sur la video suivante:

https://www.youtube.com/watch?v=DLX62G4lc44&t=16575s

Il y aussi un site de l’enseignant ici :

https://scrimba.com/learn/learnreact

ReactDOM & JSX

https://www.youtube.com/watch?v=DLX62G4lc44&t=565s

Objective: Fill in the boilerplate React code required to render an unordered list (<ul>) to the page. The list should contain 3 list items (<li>) with anything in them you want.

HINTS: import the libraries you need first use one of the libraries to render some JSX to the page

https://www.youtube.com/watch?v=DLX62G4lc44&t=1472s

import React from "react"
import ReactDOM from "react-dom"

ReactDOM.render(
    <ul>
        <li>1er élément</li>
        <li>2ème élément</li>
        <li>3ème élément</li>
    </ul>,
    document.getElementById("root"))

Functional Components Practice

https://www.youtube.com/watch?v=DLX62G4lc44&t=1234s

Objectives:

  1. Set up the basic React code from scratch

  2. Create a functional component called MyInfo that returns the following UI:

    1. An h1 with your name

    2. A paragraph with a little blurb about yourself

    3. An ordered or unordered list of the top 3 vacaton spots you’d like to visite

  3. Render an instance of that functional component to the browser Extra challenge: learn on your own (Google) how you can add some style to your page. (We will also cover this in an upcoming lesson).

https://www.youtube.com/watch?v=DLX62G4lc44&t=1472s

import React from "react"
import ReactDOM from "react-dom"

function MyInfo() {
    return (
        <div>
            <h1>Zebulus André</h1>
            <p>I'm trying to learn React</p>
            <ol>
                <li>Hawaii</li>
                <li>New York</li>
                <li>Seoul</li>
            </ol>
        </div>
    )
}

ReactDOM.render(<MyInfo />, document.getElementById("root"))

Move Components into Seperate Files

Il serait bien de mettre les composants dans un répertoire nommé components.

../_images/structure.PNG

Un fichier portant le même nom que le composant doit être créé. Il devra comporter import et export

import React from "react"

function MyInfo() {
    return (
        <div>
            <h1>Zebulus André</h1>
            <p>I'm trying to learn React</p>
            <ol>
                <li>Hawaii</li>
                <li>New York</li>
                <li>Seoul</li>
            </ol>
        </div>
    )
}

export default MyInfo

Le fichier index devra importer ce fichier dans le répertoire où il se trouve. Noter bien le Nom du composant est précédé par < suivi d’un espace />.

import React from "react"
import ReactDOM from "react-dom"
import MyInfo from "./components/MyInfo"

ReactDOM.render(<MyInfo />, document.getElementById("root"))

https://www.youtube.com/watch?v=DLX62G4lc44&t=1781s

Parent/Child Components

https://www.youtube.com/watch?v=DLX62G4lc44&t=2107s

Voici une structure dont une page internet se définirait :

../_images/structure1.PNG

Set up the React app from scratch Render an App component (defined in a separate file) Inside App, render:

  1. A Navbar component

  2. A MainContent component

  3. A Footer component

https://www.youtube.com/watch?v=DLX62G4lc44&t=2594s

Voici arborescence des fichiers :

../_images/structure2.PNG

Le fichier index.js :

import React from "react"
import ReactDOM from "react-dom"
import App from "./App"

ReactDOM.render(<App />,document.getElementById("root"))

Le composant App :

import React from "react"
import Header from "./components/Header"
import MainContent from "./components/MainContent"
import Footer from "./components/Footer"

function App() {
    return (
        <div>
            <Header />
            <MainContent />
            <Footer />
        </div>
    )
}

export default App

Le composant Header :

import React from "react"

function Header() {
    return (
        <header>
            <nav>This is a awsome navbar</nav>
        </header>
    )
}

export default Header

Le composant MainContent :

import React from "react"

function MainContent() {
    return(
        <main>
            <p>This is a paragraph</p>
            This is the main content.
            <ul>
                <li>oeléwfoé</li>
                <li>eriémcvjl</li>
                <li>ewrojdflfsd</li>
                <li>pook,mnk</li>
            </ul>
        </main>
    )
}

export default MainContent

Le composant Footer :

import React from "react"

function Footer() {
    return (
        <footer>
            this is an awsome footer. Pieds de page.
        </footer>
    )
}

export default Footer

Voici le résultat:

../_images/result.PNG

Todo App - Phase 1

  • From scratch, initialize the React app

  • Render an <App /> component

  • Create the <App /> component from scratch

  • Have the <App /> component render 3 or 4 checkboxes with paragraphs or spans next to it like you are making a todo list with some hard-coded items on it

Le fichier index.js :

import React from "react"
import ReactDOM from "react-dom"

import App from "./App"

ReactDOM.render(<App />, document.getElementById("root"))

Le component App.js :

import React from "react"

function App() {
    return (
        <div>
            <input type="checkbox" /> 
            <p>This is the first text of the checkbox 1</p>
            <input type="checkbox" />
            <p>This is the second text of the checkbox 2</p>
            <input type="checkbox" /> 
            <p>This is the third text of the checkbox 3</p>
            <input type="checkbox" />
            <p>This is the forth text of the checkbox 4</p>
        </div>
    )
}

export default App

Le résultat :

../_images/result1.PNG

Styling React with CSS Classes

On placera le fichier style.css à l’endroit suivant :

../_images/structure.png

Le fichier style.css :

body {
    margin: 0;
}

.navbar {
    height: 100px;
    background-color: #333;
    color: whitesmoke;
    margin-bottom: 15px;
    text-align: center;
    font-size: 30px;
    display: flex;
    justify-content: center;
    align-items: center;
}

En JSX on doit utiliser className=”…”

Le fichier Header.js :

import React from "react"

function Header() {
    return (
        <header className="navbar">
            <nav>This is a awsome navbar</nav>
        </header>
    )
}

export default Header

Le résultat :

../_images/result2.PNG

JSX to JavaScript and Back

Le code suivant n’affichera pas les variables firstName et lastName.

import React from "react"
import ReactDOM from "react-dom"

function App() {
    const firstName = "Bob"
    const lastName = "Ziroll"

    return (
        <h1>Hello firstName + " " + lastName !</h1>
    )
}

ReactDOM.render(<App />, document.getElementById("root"))
../_images/Capture.PNG

Si l’on veut qu’à l’intérieur de JSX, du Java Script soit interprété, il faudra faire l’usage d’accolades {}

import React from "react"
import ReactDOM from "react-dom"

function App() {
    const firstName = "Bob"
    const lastName = "Ziroll"

    return (
        <h1>Hello {firstName + " " + lastName}!</h1>
    )
}

ReactDOM.render(<App />, document.getElementById("root"))
../_images/Capture2102.PNG

En ES6 cela donnera:

import React from "react"
import ReactDOM from "react-dom"

function App() {
    const firstName = "Bob"
    const lastName = "Ziroll"

    return (
        <h1>Hello {`${firstName} ${lastName}`}!</h1>
    )
}

ReactDOM.render(<App />, document.getElementById("root"))

Un autre exemple:

import React from "react"
import ReactDOM from "react-dom"

function App() {
    const firstName = "Bob"
    const lastName = "Ziroll"
    const date = new Date()
    const hours = date.getHours()
    const minutes = date.getMinutes()

    let timeOfDay

    if (hours >= 0 && hours <= 5)
        timeOfDay = "night"
    else if (hours>5 && hours<12)
        timeOfDay="morning"
    else if (hours > 12 && hours <= 17)
         timeOfDay = "afternoon"
    else
        timeOfDay ="evening"

        return (
        <h1>Good {timeOfDay} {`${firstName} ${lastName}`} it's {hours}:{minutes}!</h1>
    )
}

ReactDOM.render(<App />, document.getElementById("root"))

Ce qui donnera:

../_images/Capture3102.PNG

Inline Styles with the Style Property

Si l’on veut mettre du style sur un h1 par exemple on mettra deux accolades un pour dire que l’on est dans du java script et l’autre pour dire que c’est un objet. Tous les noms qui ont un trait d’union devront être modifiés : enlever les traits d’union et mettre une lettre majuscule sur le nom qui venait après le trait d’union. Exemples background-color devient : backgroundColor. Si la propriété n’a que des chiffres on peut enlever les guillemets. Exemple : fontSize: 20 mais si on veut spécifier l’unité on remettra les guillements : fontSize: “20px”

<h1 style={{color:"#FF8C00"},{backgroundColor:}}> ... </h1>

Si beaucoup de style est appliqué, alors il peut être bien de noter cela comme suit :

const styles = {
  color: "#FF8C00",
  backgroundColor: "#FF2D00",
  fontSize: 20
}
return(
<h1 style={styles}> ... </h1>
...
)

L’inline Styles peut être intéressant lorsque l’on veut quelque chose de dynamique. Prenons l’exemple fait plus haut.

import React from "react"
import ReactDOM from "react-dom"

function App() {
    const firstName = "Bob"
    const lastName = "Ziroll"
    const date = new Date()
    const hours = date.getHours()
    const minutes = date.getMinutes()

    let timeOfDay

    const styles = {
        fontSize: 50
    }    

    if (hours >= 0 && hours <= 5){
        timeOfDay = "night"
        styles.color = "#04756F"
    }
    else if (hours>5 && hours<12){
        timeOfDay="morning"
        styles.color = "#8914A3"
    }
    else if (hours > 12 && hours <= 17){
        timeOfDay = "afternoon"
        styles.color = "#D90000"
    }
    else {
        timeOfDay ="evening"
        styles.color = "#6A0FDE"
    }

    

        return (
        <h1 style = {styles}>Good {timeOfDay} {`${firstName} ${lastName}`} it's {hours}:{minutes}!</h1>
    )
}

ReactDOM.render(<App />, document.getElementById("root"))

En testant à différentes heures

const date = new Date(2020,12,16,1,13)
../_images/Capture87.PNG
const date = new Date(2020,12,16,7,28)
../_images/Capture2103.PNG
const date = new Date(2020,12,16,14,47)
../_images/Capture3103.PNG
const date = new Date(2020,12,16,21,16)
../_images/Capture418.PNG

Todo App - Phase 2

Time to have fun styling! But first things first:

  1. Change the input/p combo below to be a new component called <TodoItem />. <TodoItem /> (for now) will just have the same displayed data below (every todo item is the same) hardcoded inside of it. (We’ll learn soon how to make the TodoItem more flexible)

  2. Style up the page however you want! You’re welcome to use regular CSS (in the CSS file) or inline styles, or both!

Le component TodoItem :

import React from "react"

function TodoItem() {
    return (
        <div className="todo-item">
            <input type="checkbox" />
            <p>This is the first text of the checkbox 1</p>
        </div>
    )
}

export default TodoItem

Le component App :

import React from "react"
import TodoItem from "./TodoItem"

function App() {
    return (
        <div className="todo-list">
            <TodoItem />
            <TodoItem />
            <TodoItem />
            <TodoItem />
        </div>
    )
}

export default App

Le fichier index.js :

import React from "react"
import ReactDOM from "react-dom"
import App from "./App"

ReactDOM.render(<App />,document.getElementById("root"))

Le fichier style.css :

body {
    background-color: whitesmoke;
}

.todo-list {
    background-color: white;
    margin: auto;
    width: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 1px solid #efefef;
    box-shadow: 
        0 1px 1px rgba(0, 0, 0, 0.15),
        0 10px 0 -5px #eee,
        0 10px 1px -4px rgba(0, 0, 0, 0.15),
        0 20px 0 -10px #eee,
        0 20px 1px -9px rgba(0, 0, 0, 0.15);
    padding: 30px; 
}   

.todo-item {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    padding: 30px 20px 0;
    width: 70%;
    border-bottom: 1px solid #cecece;
    font-family: Roboto, sans-serif;
    font-weight: 100;
    font-size: 15px;
    color: #333333;
}


input[type=checkbox] {
    margin-right: 10px;
    font-size: 30px;
}

input[type=checkbox]:focus {
    outline: 0;
}

Le résultat :

../_images/Capture302.PNG

On remarque que l’on a utiliser deux className qui ont été placé dans la balise <div>.

Props in React

Prenons un exemple d’une page qui a des parties similaires ici nous avons des cartes de visite de chat (voir figure ci-dessous), comportant chaqu’une une image un nom, un numéro de téléphone et un email. Nous pouvons apparenté ces cartes de visite à des components avec bien sur des données différentes comme les images, noms etc… Vient ici la notion de Props qui sont en fait les différentes données que l’on souhaite afficher dans la carte de visite.

../_images/Capture.JPG

En codant les données “en dur” nous aurons pour le fichier App.js :

import React from "react"

function App() {
    return (
        <div>
            <div>
                <img src="http://placekitten.com/300/200" />
                <h3>Mr. Whiskerson</h3>
                <p>Phone: (212) 555-1234</p>
                <p>Email: mr.whiskaz@catnap.meow</p>
            </div>
            <div>
                <img src="http://placekitten.com/400/200" />
                <h3>Fluffykins</h3>
                <p>Phone: (212) 555-2345</p>
                <p>Email: fluff@me.com</p>
            </div>
            <div>
                <img src="http://placekitten.com/400/300" />
                <h3>Destroyer</h3>
                <p>Phone: (212) 555-3456</p>
                <p>Email: ofworlds@yahoo.com</p>
            </div>
            <div>
                <img src="http://placekitten.com/200/100" />
                <h3>Felix</h3>
                <p>Phone: (212) 555-4567</p>
                <p>Email: thecat@hotmail.com</p>
            </div>
        </div>
    )
}

export default App

On aura très vite compris que s’il y avait un grand nombre de carte le fichier App.js deviendrait très grand.

En créant un component ContactCard nous pourrions simplement appeler ce component dans App.js autant de fois qu’il y a de carte de visite.

Voici le component ContactCard (dans fichier nommé ContactCard.js) :

import React from "react"

function ContactCard() {
    return(
        <div className="contact-card">
                <img src="http://placekitten.com/300/200"/>
                <h3>Mr. Whiskerson</h3>
                <p>Phone: (212) 555-1234</p>
                <p>Email: mr.whiskaz@catnap.meow</p>
            </div>
    )
}

export default ContactCard

et voici le component App (fichier App.js) :

import React from "react"
import ContactCard from "./ContactCard"

function App() {
    return (
        <div className="contacts">
            <ContactCard />
            <ContactCard />
            <ContactCard />
            <ContactCard />
        </div>
    )
}

export default App

On remarque sur la figure suivante que les données des cartes de visites sont toutes identiques. C’est là qu’il nous faut intégrer Props dans nos components.

../_images/Capture2.JPG

A l’instar des functions recevant des variables d’entrée, les component recevront les données en entrée.

Pour passer les données au component ContactCard, on procédera de la manière suivante :

Remarque: on peut mettre les données toutes sur une ligne séparée d’un espace mais il est préférable de les indenter.

import React from "react"
import ContactCard from "./ContactCard"

function App() {
    return (
        <div className="contacts">
            <ContactCard
                name="Mr. Whiskerson"
                imgURL="http://placekitten.com/300/200"
                phone="(212) 555-1234"
                email="mr.whiskaz@catnap.meow"
            />
            <ContactCard
                name="Fluffykins"
                imgURL="http://placekitten.com/400/200"
                phone="(212) 555-2345"
                email="fluff@me.com"
            />
            <ContactCard
                name="Destroyer"
                imgURL="http://placekitten.com/400/300"
                phone="(212) 555-3456"
                email="ofworlds@yahoo.com"
            />
            <ContactCard
                name="Felix"
                imgURL="http://placekitten.com/200/100"
                phone="(212) 555-4567"
                email="thecat@hotmail.com" />
        </div>
    )
}

export default App

Pour utiliser les données dans le component ContactCard, il faudra écrire

function ContactCard(props){
...

A ce moment là les données sont passées au component ContactCard. Vérifions avec un console.log :

import React from "react"

function ContactCard(props) {
    console.log(props)
    return(
        <div className="contact-card">
                <img src="http://placekitten.com/300/200"/>
                <h3>Mr. Whiskerson</h3>
                <p>Phone: (212) 555-1234</p>
                <p>Email: mr.whiskaz@catnap.meow</p>
            </div>
    )
}

export default ContactCard
../_images/Capture3104.PNG

Etant donné que le component est appelé quatre fois, les quatres objets avec leurs propriétés sont retournées.

Maintenant au lieu d’avoir les données codées en dur, mettons les données à la place.

<img src=props.imgURL/>

Ceci ne fonctionnera pas car nous sommes dans du JSX, il faut mettre enre accolades pour que se soit interprété en JS.

<img src={prop.imgURL}/>

Voici le fichier ContactCard.js:

import React from "react"

function ContactCard(props) {
    return (
        <div className="contact-card">
            <img src={props.imgURL} />
            <h3>{props.name}</h3>
            <p>Phone: {props.phone}</p>
            <p>Email: {props.email}</p>
        </div>
    )
}

export default ContactCard

Admettons maintenant que la liste des contacts serait de 50, la liste serait très longue à écrire. On peut alors paser un objet contact avec ces propriétés:

<ContactCard
   contact={{name: "Mr. Whiskerson", imgURL:
   "http://placekitten.com/300/200", phone: "(212) 555-1234"}}
   />

Notez bien la double accolade: une pour rentrer dans JS et l’autre pour dire que c’est un objet.

Les données passées ainsi ont bien meilleures allures, mais elles ne seront jamais écrite dans ce fichier mais plûtot écrites dans un fichier de données comme du JSON.

En passant cet objet contact, il nous faudra adapter le component ContactCard:

import React from "react"

function ContactCard(props) {
    return (
        <div className="contact-card">
            <img src={props.contact.imgURL} />
            <h3>{props.contact.name}</h3>
            <p>Phone: {props.contact.phone}</p>
            <p>Email: {props.contact.email}</p>
        </div>
    )
}

export default ContactCard
Props and Styling Practice

One LAST time in this course, set up a React app from scratch. Render an <App /> component App should be in its oww file. App should render 5 <Joke /> components. Each Joke should receive a “question” prop and a “punchLine” prop and render those however you’d like.

EXTRA CREDIT: Some jokes are only a punch line with no question: E.g.: “It’s hard to explain puns to kleptomaniacs because they always take things literally.” If you don’t pass in a “question” prop, how might you make it only show the punchline instead? Spend time practicing the style of your Joke component.

Voici le fichier index.js:

import React from "react"
import ReactDOM from "react-dom"
import App from "./App"


ReactDOM.render(<App />, document.getElementById("root"))

Le fichier App.js:

import React from "react"
import Joke from "./Joke"

function App() {
    return (
        <div>
            <Joke
                question="Où se cachent les canards?"
                punchline="Dans les coins-coins."
            />
            <Joke
                question="Quel animal a trois bosses?"
                punchline="Un chameau qui s'est cogné."
            />
            <Joke
                question="Comment appelle-t-on un avion qui rebondit?"
                punchline="Un boing."
            />
            <Joke
                question="Pourquoi le père noël a-t-il une barbe blanche?"
                punchline="Pour ne pas être confondu avec le petit chaperon rouge."
            />
            <Joke
                punchline="Vaut mieux prévenir que guérir."
            />
        </div>
    )
}

export default App

Le fichier Joke.js:

import React from "react"

function Joke(props) {
    return(
        <div>
            <h3>Question: {props.question}</h3>
            <h3>Réponse: {props.punchline}</h3>
            <br/>
        </div>
    )
}
export default Joke

On remarque l’utilisation de

<br/>

pour insérer une ligne vide entre chaque joke. On aurait aussi pû utiliser

<hr/>

pour afficher une ligne de séparation

On remarque où il n’y pas de question la marque Question: subsiste. Pour faire disparaître ceci on utilisera la commande suivante style et display:

<h3 style={{display: props.question ? "block" : "none"}}>Question:
{props.question}<h3/>

un autre moyen (plus difficile à comprendre:

<h3 style={{display: !props.question && "none"}}> Question:
{props.question}<h3/>
../_images/Capture2104.PNG

et le fichier Joke.js:

import React from "react"

function Joke(props) {
    return(
        <div>
            <h3 style={{display: props.question ? "block" : "none"}}>Question: {props.question}</h3>
            <h3>Réponse: {props.punchline}</h3>
            <br/>
        </div>
    )
}
export default Joke

En mettant une couleur grise aux réponses qui ne possèdent pas de question:

import React from "react"

function Joke(props) {
    const styles1 = {
        display: props.question ? "block" : "none",
        color: "#FF8C00",
    }
    const styles2 = {
        color: !props.question && "#888888"
    }
    return (
        <div>
            <h3 style={styles1}>Question: {props.question}</h3>
            <h3 style={styles2}>Réponse: {props.punchline}</h3>
            <br />
        </div>
    )
}
export default Joke
../_images/Capture3105.PNG

Mapping Components

Dans les exemples précédents, les données ont été codées en dur. La plupart du temps les données affichées par React proviennent de requêtes http par le biais d’API. Ces données sont stockées dans une base de données qui sont ensuite exportée dans un fichier JSON. Comme nous ne savons pas encore utiliser ces moyens, nous nous servirons des données stockées dans un fichier sous forme d’un tableau.

Voici le fichier JokesData.js:

const JokesData = [
    {
        question: "Où se cachent les canards",
        punchline: "Dans les coins-coins"
    },
    {
        question: "Quel animal a trois bosses?",
        punchline: "Un chameau qui s'est cogné."
    },
    {
        question: "Comment appelle-t-on un avion qui rebondit?",
        punchline: "Un boing."
    },
    {
        question: "Pourquoi le père noël a-t-il une barbe blanche?",
        punchline: "Pour ne pas être confondu avec le petit chaperon rouge."
    },
    {
        punchline: "Vaut mieux prévenir que guérir."
    }
]

Ce tableau comporte des éléments qui sont des objets avec trois propriétés : id, question et punchline.

On note la commande export default JokeData, pour que l’on puisse utiliser les données dans App.js

Comment peut-on prendre les données d’un tableau et les convertir en nombre de components? Nous allons utiliser une fonction d’ordre supérieur dans un tableau. Qu’est que c’est que ça? prenons exemple :

../_images/Capture419.PNG

nous pouvons réduire cette function en arrow function :

../_images/Capture1102.PNG

Comme nous avons qu’un paramètre en entrée nous pouvons omettre les parenthèses :

../_images/Capture2105.PNG

Et comme une arrow function retourne dans tous les cas une valeur on peut omettre le mot return et mettre tout sur une ligne.

../_images/Capture3106.PNG

Et voici le résultat:

../_images/Capture420.PNG

On remarque que cette function d’ordre supérieur applique sur tous les éléments du tableau une multiplication par 2. On remarque aussi que map ne modifie pas le tableau original. Il faut donc attribuer le résultat à un nouveau tableau (ici doubled)

D’autre fonction d’ordre supérieur sont intéressantes à étudier comme filter et reduce.

En appliquant le même raisonnement à notre tableau dataJokes. Ce que nous souhaitons appliquer à tous les éléments de dataJokes, c’est d’avoir une ligne comme ressemblant à ceci :

../_images/Capture513.PNG

et voici donc la commande map qui fait cela :

../_images/Capture614.PNG

Maintenant nous pouvons mettre ce tableau de components dans React et JSX fait cela très bien!

import React from "react"
import Joke from "./Joke"
import JokesData from "./JokesData"

function App() {

    const jokeComponents = JokesData.map(item => <Joke question={item.question} punchline={item.punchline} />)

    return (
        <div>
            {jokeComponents}
        </div>
    )
}

export default App

Et le résultat est identique. On déplore toutefois un avertissement :

../_images/Capture713.PNG

Ceci est dû au mappage du tableau. Il faut inclure une clé (key) unique par élément. On aurait pû choisir key=question car on sait qu’il n’y aura pas deux questions identiques. Le mot key doit obligatoirement être choisi. Dans un fichier data, ily a souvent une propriété id (qui est unique) utilisons-la pour notre tableau:

../_images/Capture810.PNG

Et voici le fichier final de App.js:

import React from "react"
import Joke from "./Joke"
import JokesData from "./JokesData"

function App() {

    const jokeComponents = JokesData.map(item => <Joke key={item.id} question={item.question} punchline={item.punchline} />)

    return (
        <div>
            {jokeComponents}
        </div>
    )
}

export default App

Et le component Joke qui n’a pas bougé depuis l’exercie précédent :

import React from "react"

function Joke(props) {
    const styles1 = {
        display: props.question ? "block" : "none",
        color: "#FF8C00",
    }
    const styles2 = {
        color: !props.question && "#888888"
    }
    return (
        <div>
            <h3 style={styles1}>Question: {props.question}</h3>
            <h3 style={styles2}>Réponse: {props.punchline}</h3>
            <br />
        </div>
    )
}
export default Joke

Commme déjà cité plus haut il y a plusieurs méthodes relatif au tableau qui sont bons à voir ou à revoir (tapez MDN et la méthode dans google):

  • filter

  • map

  • sort

  • reduce

  • every

  • some

  • find

  • findindex

Mapping Components Practice

Given a list of products (as an array of objects, as seen in vschoolProducts) render a <Product /> component (which you’ll also to create) for each product in the list.

Make sure to use the array’s .map() method to create thes components, and don’t forget to pass a key prop to it to avoid the warning.

Voici le fichier vschoolProducts.js:

const products = [
    {
        id: "1",
        name: "pencil",
        price: 1,
        description: "Perfect for those who can't remember things! 5/5 Highly recommend."
    },
    {
        id: "2",
        name: "Housing",
        price: 0,
        description: "Housing provided for out-of-state students or those who can't commute"
    },
    {
        id: "3",
        name: "Computer Rental",
        price: 300,
        description: "Don't have a computer? No problem!"
    },
    {
        id: "4",
        name: "Coffee",
        price: 2,
        description: "Wake up!"
    },
    {
        id: "5",
        name: "Snack",
        price: 0,
        description: "Free Snacks!"
    },
    {
        id: "6",
        name: "Rubber Duckies",
        price: 3.50,
        description: "For those who make mistakes"
    }
]

export default products

Normalement les données du tableau mappé devrait ressembler à ça:

../_images/Capture422.PNG

c’est-à-dire que nous passions les propriétés de l’objet. On peut aussi passer l’objet entier et sortir les propriétés dans le composant enfant (ici Product)

Voilà le fichier App.js:

import React from "react"
import Product from "./Product"
import productsData from "./vschoolProducts"

const productComponents = productsData.map(item => <Product key={item.id} product={item} />)

function App() {
    return (
        <div>
            {productComponents}
        </div>
    )
}

export default App

Remarque: Quand on export des données d’un fichier ici du fichier vschoolProducts.js nous l’exportons avec la commande suivante: export default products, mais il est possible de l’importer avec un autre nom: dans le fichier App nous l’importons avec le nom productsData (import productsData from “./vschoolProducts”

Et le fichier Product.js:

import React from "react"

function Product(props) {
    return (
        <div>
            <h2>{props.product.name}</h2>
            <p>{props.product.price.toLocaleString("en-US", { style: "currency", currency: "USD" })} - {props.product.description}</p>
        </div>
    )
}

export default Product

Pour afficher l’unité du prix, on s’est servi de la méthode string.

Le résultat final:

../_images/Capture2106.PNG

Todo App - Phase 3

Let’s practice props and mapping components on our todo list app:

I’ve created a js file with some todos data in it, which I’m imported into this files. (Normally this data would come from an API call, not a local file).

Challenge: Using the array map method, render a child component for each todo item in the todosData array and pass the relevant data to it.

L’exercice est très similaire à l’exercice précédent, j’exposerai seulement les fichiers comme résultat. Sauf pour la partie case à cocher, j’expliquerai comment coché avec la propriété checked.

Voici le fichier todosData.js:

const todosData = [
    {
        id: 1,
        text: "Take out the trash",
        completed: true
    },
    {
        id: 2,
        text: "Grocery shopping",
        completed: false
    },
    {
        id: 3,
        text: "Clean gecko tank",
        completed: false
    },
    {
        id: 4,
        text: "Mow lawn",
        completed: true
    },
    {
        id: 5,
        text: "Catch up on Arrested Development",
        completed: false
    }
]

export default todosData

Voici le fichier index.js (rien de nouveau dans celui-ci):

import React from "react"
import ReactDOM from "react-dom"

import App from "./App"

ReactDOM.render(<App />, document.getElementById("root"))

Voici le fichier App.js:

import React from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"

function App() {
    const todoItems = todosData.map(item => <TodoItem key={item.id} item={item} />)
    return (
        <div>
            { todoItems}
        </div>
    )
}

export default App

Attention de bien mettre key pour empêcher les doublons.

et le fichier TodoItem.js:

import React from "react"

function TodoItem(props) {
    return (
        <div className="todo-item">
            <input type="checkbox" checked={props.item.completed} />
            <p>{props.item.text}</p>
        </div>
    )
}

export default TodoItem 

On remarque l’utilisation de la propriété checked:

<input type="checkbox" checked={props.item.completed} />

Pour afficher un vu suivant props.item.completd fixé par true ou false dans le fichier todosData.js. Le navigateur affiche un message d’erreur car cela fige la case à cocher (plus de possibilité de cocher ou de décocher manuellement). Mais cela va être résolut par la suite.

Class-based Components

Si l’on veut approfondir avec React, on sera limité par l’utilisation des Functional Component. C’est pourquoi nous allons utiliser les Class-based Components. Pour l’instant nous allons introduire les Class-based Components pour reproduire exactement ce que les fonctions peuvent faire. Mais dans les prochaines leçons nous allons découvrir que les Class-based Components peuvent faire bien plus, comme States, Livecycle Methods.

Découvrons maintenant comment convertir une Functional Component en Class-based Component:

import React from "react"

function App() {
   return (
      <div>
         <h1>Code goes here</h1>
      <div>
   )
}

pour une Class-based Component, il n’y pas de parenthèses commme pour une Functional Component.

class App extends React.Component


export default App

Chaque Class-based Component à besoi d’au moin une méthode et cette méthode est la méthode render et cela doit impérativement être écrit de la cette manière :

class App extends React.Component {
   render() {

   }
}

export default App

La méthode render va retourner exactement la même chose que ce que l’on a pour les Functional Components. Nous pouvons donc copier ce qu’il y a dans dans return avec le mot return de la Functional Component :

class App extends React.Component {
   render() {
      return (
         <div>
            <h1>Code goes here</h1>
         </div>
      )
   }
}

export default App

Cette Class-based Component est identique à la Functional Component.

Voyons maintenant la méthode render(), à chaque fois que l’on désire faire une logique d’affichage, comme par expemple l’exercice d’affichage du texte en fonction de l’heure que l’on avait fait plus haut, le code sera inséré après la méthode render() et avant return :

class App extends React.Component {
   render() {
      const date = new Date();
      return (
         <div>
            <h1>Code goes here</h1>
         </div>
      )
   }
}

export default App

L’inline styling pourra aussi y être placé.

On peut créé des méthodes après class et avant render() et les appeler après la méthode render() avec this.yourMehodHere():

class App extends React.Component {

   yourMethodeHere() {

   }

   render() {
      const style = this.yourMethodeHere()
      return (
         <div>
            <h1>Code goes here</h1>
         </div>
      )
   }
}

export default App

Pour l’utilisation de props on fera précédé le mot props par this. :

class App extends React.Component {

   yourMethodeHere() {

   }

   render() {
      return (
         <div>
            <h1>Code goes here{this.props.whatever}</h1>
         </div>
      )
   }
}

export default App

En ayant l’habitude d’utiliser props dans des functional Component, on oubliera vite le mot this. dans une Class-based Component.

Class-based Components Practice

Pour cette exercice nous allons mettre tous les composants dans un même fichier. Normalement, chaque composant est mis dans un fichier séparé.

Challenge:

  1. Convert all 3 components to be class-based

  2. Fix the small bug

import React from "react"
import ReactDOM from "react-dom"

// #1

function App() {
    return (
        <div>
            <Header />
            <Greeting />
        </div>
    )
}

// #2

function Header(props) {
    return (
        <header>
            <p>welcome, {props.username}!</p>
        </header>
    )
}

// #3

function Greeting() {
    const date = new Date()
    const hours = date.getHours()
    let timeOfDay

    if (hours < 12) {
        timeOfDay = "morning"
    } else if (hours >= 12 && hours < 17) {
        timeOfDay = "afternoon"
    } else {
        timeOfDay = "night"
    }
    return (
        <h1>Good {timeOfDay} to you, sir or madam!</h1>
    )
}

ReactDOM.render(<App />, document.getElementById("root"))

Pour convertir une Functional Component en Class-base Component :

  1. Remplacer le mot function en class

  2. Enlever les () après le nom de la fonction

  3. Ecrire extends React.Component

  4. Ecrire render()

  5. Si il y a du code pour styling, etc… le mettre juste après render()

  6. Copier return et son contenu

  7. Si il y a des props, mettre {this.props.whatever}

import React from "react"
import ReactDOM from "react-dom"

// #1

class App extends React.Component {
    render() {
        return (
            <div>
                <Header />
                <Greeting />
            </div>
        )
    }
}

// #2

class Header extends React.Component {
    render() {
        return (
            <header>
                <p>welcome, {props.username}!</p>
            </header>
        )
    }
}

// #3

class Greeting extends React.Component {
    render() {
        const date = new Date()
        const hours = date.getHours()
        let timeOfDay

        if (hours < 12) {
            timeOfDay = "morning"
        } else if (hours >= 12 && hours < 17) {
            timeOfDay = "afternoon"
        } else {
            timeOfDay = "night"
        }
        return (
            <h1>Good {timeOfDay} to you, sir or madam!</h1>
        )
    }
}

ReactDOM.render(<App />, document.getElementById("root"))

On voit qu’il y un message d’erreur ‘props’ is not defined. Ceci est normal, car dans une class on doit utiliser this.props.whatever

Aussi, il faut passer les données à props

<Header username="windwaver" />

Voici le code final:

import React from "react"
import ReactDOM from "react-dom"

// #1

class App extends React.Component {
    render() {
        return (
            <div>
                <Header username="windwaver" />
                <Greeting />
            </div>
        )
    }
}

// #2

class Header extends React.Component {
    render() {
        return (
            <header>
                <p>welcome, {this.props.username}!</p>
            </header>
        )
    }
}

// #3

class Greeting extends React.Component {
    render() {
        const date = new Date()
        const hours = date.getHours()
        let timeOfDay

        if (hours < 12) {
            timeOfDay = "morning"
        } else if (hours >= 12 && hours < 17) {
            timeOfDay = "afternoon"
        } else {
            timeOfDay = "night"
        }
        return (
            <h1>Good {timeOfDay} to you, sir or madam!</h1>
        )
    }
}

ReactDOM.render(<App />, document.getElementById("root"))

Et le résultat:

../_images/Capture423.PNG

State

Voilà, nous sommes arrivés au point le plus important de React. C’est la compréhension de state. State est utilisé pour la gestion des données. State permet de modifier les données. La différence entre state et props c’est que les données passées à un autre component par props ne peuvent être changées, elle sont immuables. State permet cela. On ne pourra par exemple jamais attribué une valeur à props comme par exemple :

../_images/Capture.png

Chaque fois que l’on veut modifier une donnée on devra passer par state. Et state ne peut être invoqué que par une Class-based Component.

Pour introduire state dans une Class-based Component, il nous faut écrire la méthode constructor() une ligne en dessous de class… La méthode constructor() est issue du Java Script. Elle initialise la class.

Pour se familiariser avec class voir Classes ou voir la vidéo suivante :

https://scrimba.com/p/p4Mrt9/cQnMDHD

Ensuite en dessous il nous faut écrire super() cette méthode à pour but de tirer quelque goodies de React.Component. Un des goodies est la méthode set state() que l’on verra plus loin. En dessous de super() on mettra this.state = {} qui est un objet avec une propriété que l’on peut appeler dans le Component.

Voici le fichier:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            answer: "Yes"
        }
    }

    render() {
        return (
            <div>
                <h1>Is React important to know? {this.state.answer}</h1>
            </div>
        )
    }
}

export default App

et le résultat :

../_images/Capture1.png

Le this.state initialise notre state. Le fait particulier de state est que l’on peut modifier sa valeur plus tard. On peut passer state à un component enfant en invoquant props.

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            answer: "Yes"
        }
    }

    render() {
        return (
            <div>
                <h1>Is React important to know? {this.state.answer}</h1>
                <ChildComponent answer = {this.state.answer}/>
            </div>
        )
    }
}

export default App

Un truc cool avec state est quand on modifie la variable state tous les composant utilisant sa valeurs vont être rafraîchit. Nous verrons ceci plus tard avec la commande set state.

State Practice

Challenge:

Given an incomplete class-based component without a constructor, add a constructor and initialiye state to fix the brocken component.

import React from "react"

class App extends Component() {
    return(
        <div> 
           <h1>{this.state.name}</h1>
           <h3>{this.state.age} years old</h3>
        </div >
    )
}

export default App
import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            name: "Terry",
            age: 27
        }
    }
    render() {
        return (
            <div>
                <h1>{this.state.name}</h1>
                <h3>{this.state.age} years old</h3>
            </div >
        )
    }
}



export default App

Et le résultat:

../_images/Capture424.PNG

State Practice 2

Given a stateless functional component, add state to it. State should have a property called isLoggedIn wich is a boolean (true if logged in, false if not). Then, give your best shot at rendering the word “in” if the user is logged in or “out” if the user is logged out.

import React from "react"

function App() {
    return (
        <div>
            <h1>You are currently logged (in/out)</h1>
        </div>
    )
}

export default App

voici pour la première partie:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            isLoggedIn: true
        }
    }

    render() {
        return (
            <div>
                <h1>You are currently logged (in/out)</h1>
            </div>
        )
    }
}

export default App

pour la dernière partie on utilisera du conditional rendering. Attention de bien le placer entre render() et return() :

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            isLoggedIn: false
        }
    }

    render() {
        let wordDisplay
        if (this.state.isLoggedIn === true) {
            wordDisplay = "in"
        }
        else {
            wordDisplay = "out"
        }
        return (
            <div>
                <h1>You are currently logged {wordDisplay}</h1>
            </div>
        )
    }
}

export default App

et le résulat :

../_images/Capture425.PNG ../_images/Capture2107.PNG ../_images/Capture3107.PNG ../_images/Capture426.PNG

Todo App - Phase 4

In the previous iteration of this todo list app, we pulled in todos data from a JSON file and mapped over it to display the todo items. Eventually we’ll want to be able to modify the data, which will only happen if we’ve “loaded” the data in to the component’s state

Challenge: Change the <App /> component into a stateful class component and load the imported todosData into state.

import React from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"

function App() {
    const todoItems = todosData.map(item => <TodoItem key={item.id} item={item} />)
    return (
        <div>
            { todoItems}
        </div>
    )
}

export default App

en changeant en class:

import React from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            todo: todosData
        }
    }
    render() {
        const todoItems = this.state.todo.map(item => <TodoItem key={item.id} item={item} />)
        return (
            <div>
                { todoItems}
            </div>
        )
    }
}

export default App

Handling Events in React

Handling Events sont des événements tel que l’utilisateur déclenchera quand il clique sur un élément ou passe la souris sur un élément. Vous serez sûrement familié avec le language html qui est le suivant:

<button onclick="myFunction()">Click me</button>

Avec React c’est presque la même chose: les événements sont repris du Java Script, ils auront une majuscule.Ppour l’évémement de ci-dessus cela deviendrait:

onClick

Pour:

onmouseover

cela devient:

OnMouseOver

Ici quelques nom d’événement à réviser:

https://reactjs.org/docs/events.html#supported-events

Voici un code avec un bouton sans événement:

../_images/Capture427.PNG

Administrons une fonction à l’événement onClick à ce bouton:

../_images/Capture2108.PNG

et le résultat quant on clique sur le bouton:

../_images/Capture3108.PNG

Ou en appelant la fonction déclarée séparément:

../_images/Capture428.PNG

Un petit exercice: en se référant à la page ci-dessous:

https://reactjs.org/docs/events.html#supported-events

trouver et écrire un événement lorsque le pointeur de la souris passe sur l’image, un événement se déclenche.

../_images/Capture514.PNG ../_images/Capture615.PNG

Il est clair que faire sortir le résultat d’un événement en console.log n’est pas intéressante. En fait les événements pourront modifié les state et c’est ce qui va faire une app très robuste.

Todo App - Phase 5

Challenge: Get rid of our warning about not having an onChange on our input. For now, the function that runs onChange can simply console.log something.

Voici le code comme il était resté au dernier exercice:

import React from "react"

function TodoItem(props) {
    return (
        <div className="todo-item">
            <input type="checkbox" checked={props.item.completed} />
            <p>{props.item.text}</p>
        </div>
    )
}

export default TodoItem 

Voici la solution:

import React from "react"

function TodoItem(props) {
    return (
        <div className="todo-item">
            <input
                type="checkbox"
                checked={props.item.completed}
                onChange={() => console.log("changed")}
            />
            <p>{props.item.text}</p>
        </div>
    )
}

export default TodoItem 

On remarque pour plus de clarté, on peut mettre à la ligne ce qu’il y a entre <input …. et />

Changing State

Voici le moment venu d’apprendre comment on change la valeur de state. Prenons un exemple: un compteur (count) avec un bouton en dessous et lorsque l’on clique sur le bouton cela va nous changer la valeur de count.

../_images/Capture429.PNG

voici le code de départ:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button> Change!</button> 
            </div >
        )
    }
}

export default App

Petit exercie que faut il mettre pour que quand on appuie sur le boutton quelque chose apparaisse dans le console.log?

On doit rajouter un évenement onClick:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            count: 0
        }
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={() => console.log("clicked")}> Change!</button> 
            </div >
        )
    }
}

export default App

Au lieu d’une arrow function (ici un fonction anonyme en ligne) créons une méthode et déclarons-la au bon endroit. Pour savoir où la déclarer, voici une explicaton sur les zones:

La partie render() est réservée pour les méthodes utilisée par React, entre constructor() et render() on peut mettre autant de méthodes que l’on veut.

Une forte convention que les gens ont, est de l’appeler handleClick lorsque on l’associe à l’événement onClick. Attention de bien mettre this.handlclick quand on appelle la méthode.

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            count: 0
        }
    }
    handleClick() {
        console.log("clicked!")
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.handleClick}> Change!</button>
            </div >
        )
    }
}

export default App

Bon ceci est enuyeux, changeons maintenant la valeur de state (ici de count).

Pour changer la valeur de count, on est tenté de changer directement avec la commande suivante:

handleClick(){
   this.state.count++
}

Mais ceci ne se fait pas on ne change jamais la valeur originale de state. On crée une nouvelle version de state. On peut apparenté ceci aux habit que l’on porte. On ne changera pas la couleur de l’habit en le peignant, on changera l’habit. Et c’est la même chose pour state. Rappelons nous lorsque nous évoquons extends React.Component, il y quelques goodies qui nous sont offerts comme la méthode setState(). A chaque fois que l’on voudra changer state nous utiserons cette méthode. Il y deux choses que l’on peut passer à cette méthode en paramètre : prenons la plus simple, une nouvelle version de state. State est un un objet et l’on peut passer un nouvel objet comme ici :

this.setState({count: 1})

nous arrivons à une erreur : à chaque fois que l’on crée une class method, nous seront obligé de “bind” cette méthode à notre class. Si vous n’êtes pas tout à fait familié avec “bind” ne vous en fait pas trop. Sachez que chaque fois que vous faite une méthode avec setState, il faudra la “binder” avec votre classe. Et le moyen de “binder” se fait à l’intérieur de constructor().

this.handleClick = this.handleClick.bind(this)

Ce que fait cette commande est d’assurer que la méthode handleClick soit bound au contexte de this au travers de la classe.

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            count: 0
        }
        this.handleClick=this.handleClick.bind(this)
    }
    handleClick() {
        this.setState({ count: 1 })
    }
    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.handleClick}> Change!</button>
            </div >
        )
    }
}

export default App

Résultat quand on click sur bouton la valeur passe de 0 à 1.

../_images/Capture2109.PNG

Lorsque l’on n’a pas besoin de connaître le résultat de la version d’avant de state, l’assignation du nouveau objet fera l’affaire. Par contre, lorsque l’on veut additioner 1 à count, il nous faut connaître l’état précédent. Pour ce faire on fera passer une fonction :

handleClick() {
   this.setState(prevState => {
      return {
         count: prevState.count +1
      }
   })
}

Résultat : Lorsque l’on clique sur le bouton le compteur est incrémenter de 1.

../_images/Capture2109.PNG

Récapitulons :

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            count: 0
        }
        this.handleClick = this.handleClick.bind(this)
    }
    handleClick() {
        this.setState(prevState => {
            return {
                count: prevState.count + 1
            }
        })
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.handleClick}> Change!</button>
            </div >
        )
    }
}

export default App
  1. Nous avons:

    <h1>{this.state.count}</h1>
    

    qui affiche notre state ici la propriété count

  2. Cette propriété a été initialisée dans constructor

    ../_images/Capture430.PNG
  3. On a ajouter un event onClick à notre button qui actionne notre méthode handleClick. Cette méthode a été crée dans la class App

    ../_images/Capture515.PNG ../_images/Capture616.PNG
  4. Parce que la méthode handleClick utilise la méthode setState qui vient de extends React.Component, nous devons être sûr de “binder” dans constructor

    ../_images/Capture714.PNG
  5. Une fois que la méthode handleClick a été “bindé”, on peut utiliser la méthode setState pour soit attribué un objet pour créer une nouvel version de state (sans se préoccupé de la version précédente)

    ../_images/Capture812.PNG

    , soit de passer une fonction qui passe le paramètre comme un objet de la version précédente et returne la nouvelle version après avoir utilisé la version précédente.

    ../_images/Capture912.PNG

Cette partie de state est très importante à connaître car elle sera utilisée souvent lors des prochaines leçons. Donc effacer tout le code et regarder si vous pouvez tout le refaire de tête. C’est le meilleure moyens d’en prendre connaissance.

Todo App - Phase 6

Dans cet exercice, nous allons modifier le code de notre Todo App de telle façon que lorsque l’on clique sur une case à cocher, la case sera cochée ou décochée. Nous allon en fait modifier le state.

/**
 * Let's make it so our checkbox can actually mark our todo as complete or incomplete!
 * This challenge is a little more involved than some of the past ones. Check the comments
 * in the code for some help on accomplishing this one
 * 
 * Challenge:
 * 1. Create an event handler in the App component for when the checkbox is clicked (which is an
 *  `onChange`event)
 *      a. This method will be the trickest part. Check the comments in the stubbed-out method below
 * for some pseudocode to help guide you through this part
 * 2. Pass the method down to the TodoItem component
 * 3. In the TodoItem component, make it so when the `onChange` event happens, it calls the
 * `handleChange` method and passes the id of the todo into the function
 */

import React from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            todo: todosData
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(id) {
        /**
         * Update state so that the item with the given id flips `completed` from false to true
         * (or vise versa)
         * Remember not to modify prevState directly, but instead to return a new version of state with
         * with the change you want included in that update. (Think how you might use the `.map)`
         * method to do this
         */
    }

    render() {
        const todoItems = this.state.todo.map(item => <TodoItem key={item.id} item={item} />)
        return (
            <div>
                { todoItems}
            </div>
        )
    }
}

export default App

Faisons cela dans un ordre quelquonque : toute d’abord faisons un console.log à notre méthode handleChange :

../_images/Capture432.PNG

pour tester lorsqu’on clique sur une case l’id est bien affiché. Maintenant, faisons les points 2. et 3. :

../_images/Capture2110.PNG

Donc le point 2, dit qu’il faut passer notre méthode handleChange à notre composant TodoItem:

../_images/Capture3109.PNG

et maintenant notre TodoItem reçoit notre méthode: props.handleChange. Prenez note que la méthode prend id comme paramètre et que OnChange reçoit une propriété event. Cela n’est pas suffisant d’appeler notre props de cette manière :

../_images/Capture433.PNG

car onChange ne pas recevoir une propriété event, mais seulement un objet event à la place.

on insérer une fonction qui émet une propriété event et qui appelle la méthode handleChange avec comme paramètre props.item.id.

../_images/Capture516.PNG

Dans ce cas nous n’allons pas utiliser event on peut donc juste l’effacer:

../_images/Capture617.PNG

Faisons un test en cliquant sur les cases à cocher on voit que l’id correspondant s’affiche correctement:

../_images/Capture715.PNG

Voici le code complet de TodoItem.js:

import React from "react"

function TodoItem(props) {
    return (
        <div className="todo-item">
            <input
                type="checkbox"
                checked={props.item.completed}
                onChange={() => props.handleChange(props.item.id)}
            />
            <p>{props.item.text}</p>
        </div>
    )
}

export default TodoItem 

Voilà les points 2 et 3 sont achevés. Occupons-nous d’actualisé notre state :

../_images/Capture813.PNG

Cette partie est la plus trickie. Nous devons nous occuper de l’entier du tableau, car nous enregistrons notre tableau dans notre state et nous ne voulons jamais changer notre state directement, nous ne pouvons pas simplement changer l’élément du bon id en flippant sa valeur de true à false ou vice versa car cela modifie la version original de state. A l’opposé nous allons créer un nouveau tableau en conservant tous les éléments à l’exception de l’élément qui passera de true à false ou vice versa. Pour ce faire, nous allons utiliser la méthode map car comme nous le savons déjà celle-ci retournera un tout nouveau tableau.

Donc ce que l’on va d’abord faire c’est utiliser setState avec une fonction pour conserver la version originale : Nous allons utiliser map pour faire une boucle de notre tableau original.

prevState.todos est notre ancienne version de todos. Nous allons parcourir tous les éléments de ce tableau avec

todo => {
  if (todo.id === id)}

et cet id est l’élément que l’on veut basculer.

ensuite nous allons retourner todo pour mettre ce nouveau tableau dans updateTodos.

../_images/Capture913.PNG

encore un return pour assigner le nouveau tableau à la propriété todos de l’objet.

../_images/Capture1012.PNG

Et voici le code complet de App.js:

/**
 * Let's make it so our checkbox can actually mark our todo as complete or incomplete!
 * This challenge is a little more involved than some of the past ones. Check the comments
 * in the code for some help on accomplishing this one
 * 
 * Challenge:
 * 1. Create an event handler in the App component for when the checkbox is clicked (which is an
 *  `onChange`event)
 *      a. This method will be the trickest part. Check the comments in the stubbed-out method below
 * for some pseudocode to help guide you through this part
 * 2. Pass the method down to the TodoItem component
 * 3. In the TodoItem component, make it so when the `onChange` event happens, it calls the
 * `handleChange` method and passes the id of the todo into the function
 */

import React from "react"
import TodoItem from "./TodoItem"
import todosData from "./todosData"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            todos: todosData
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(id) {
        /**
         * Update state so that the item with the given id flips `completed` from false to true
         * (or vise versa)
         * Remember not to modify prevState directly, but instead to return a new version of state with
         * with the change you want included in that update. (Think how you might use the `.map)`
         * method to do this
         */
        this.setState(prevState => {
            const updatedTodos = prevState.todos.map(todo => {
                if (todo.id === id) {
                    todo.completed = !todo.completed
                }
                return todo
            })
            return {
                todos: updatedTodos
            }
        })
    }

    render() {
        const todoItems = this.state.todos.map(item => <TodoItem key={item.id} item={item} handleChange={this.handleChange} />)
        return (
            <div>
                { todoItems}
            </div>
        )
    }
}

export default App

Le test a bien fonctionné en cliquant sur une case ça bascule bel et bien.

Lifecycle Methods Part 1

Chaque component sous React possède en arrière plan des méthodes de cycle de vie. Comme la vie humaine qui a une naissance, …, et une mort. Tous les éléments React vont traverser des événements lorsqu’ils sont rendus (rendered) et mis à jour. L’équipe de React a déprecié trois Lifecycle methods. Au lieu de prendre chaqu’une des méthodes une à une, nous allons présenter les méthodes les plus utilisées. Pour une introduction plus complète à ces méthodes veuillez vous référer à ce site: https://engineering.musefind.com/react-lifecycle-methods-how-and-when-to-use-them-2111a1b692b1

et le site officiel de l’équipe React:

https://reactjs.org/blog/2018/03/29/react-v-16-3.html#component-lifecycle-changes

Conditional Rendering

Le Conditional Rendering peut être appliqué de beaucoup de façon différentes. Proposons une façons dans le code suivant:

import React from "react"
import Conditional from "./Conditional"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            isLoading: true
        }
    }

    componentDidMount() {
        setTimeout(() => {
            this.setState({
                isLoading: false
            })
        }, 1500)
    }
    render() {
        return (
            <div>
                <Conditional isLoading={this.state.isLoading} />
            </div>
        )
    }
}

export default App

Dans le code de ci-dessus, on a ajouté un state avec une propriété isLoading à true. Ceci est souvent utilisé lors d’appel vers un API, et pendant le chargement on veut afficher quelque chose pour dire qu’il y a un processus en cours. Ainsi l’utilisateur n’aura pas l’impression que l’app a crashé. Le Conditional Rendering intervient là. Nous avons un autre Component Conditional qui reçoit le props isLoading avec la version courante de state : this.state.isLoading. Dans Conditional nous allons ajouter ce que l’on veux afficher à l’écran.

Rappelez-vous que la méthode componentDidMount() est une chance pour nous d’écrire du code pour qu’il s’execute avant que notre Component ici App s’execute à l’écran pour la première fois. Le code compris dans componentDidMount est en fait un code qui simule une requête API. Nous avons mis un délai de 1500 via la fonction setTimeout qui va faire basucler la propriété isLoading à false. Une fois que ça bascule à false, le component Conditional va recevoir une nouvel prop, ce qui va réexuter la méthode render() ce qui va faire à nouveau s’excuter le component Conditional qui est une functional component et selon ce qui a dedans faire executer quelque chose d’autre. Donc notre component Conditional va recevoir une nouvel prop. Avant d’aller plus loin vérifions que notre component Conditional fonctionne, en mettant un console.log(props.isLoading) : ci-dessous le component Conditional:

import React from "react"

function Conditional(props) {
    console.log(props.isLoading)
    return (
        <div>
            <h1>Temp</h1>
        </div>
    )
}

export default Conditional

Lorsque l’on rafraîchit la page, true s’affiche tout de suite et 1.5s plus tard false s’affiche.

Maintenant au lieu d’afficher Temp nous allons mettre une condition qui affichera quelque chose de différent suivant la valeur de isLoading.

import React from "react"

function Conditional(props) {
    if (props.isLoading === true) {
        return (
            <h1>Loading...</h1>
        )
    } else {
        return (
            <div>
                <h1>Some cool stuff about conditional rendering</h1>
            </div>
        )
    }
}

export default Conditional

Le résultat est que ça affiche isLoading pendant 1.5s et ensuite Some cool stuff…

Ce code utilise du pur Java Script avec if. On préférera réécrire ce code de la façon suivante avec ce mode de conditionnement mais c’est un choix personnel bien-sûr :

condition ? statement if true : statement if false

import React from "react"

function Conditional(props) {
    return (
        <div>
            <h1>Navbar</h1>
            {props.isLoading ? <h1>Loading...</h1> : <h1>Some cool stuff about conditional rendering</h1>}
            <h1>Footer</h1>
        </div>
    )
}

export default Conditional

Nous avons mis ce code dans un component Conditional, mais le meilleur endroit pour mettre ce genre de code est dans le component App. Car c’est dans la méthode render() qui est le plus approprié à dire qu’un composant doit être executé ou pas.

Voici le code App.js et Conditional.js:

import React from "react"
import Conditional from "./Conditional"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            isLoading: true
        }
    }

    componentDidMount() {
        setTimeout(() => {
            this.setState({
                isLoading: false
            })
        }, 1500)
    }
    render() {
        return (
            <div>
                {this.state.isLoading ?
                    <h1>Loading..</h1> :
                    <Conditional />}
            </div>
        )
    }
}

export default App
import React from "react"

function Conditional() {
    return (
        <div>
            <h1>Some cool stuff about conditional rendering</h1>
        </div>
    )
}
export default Conditional

Conditional Rendering Part 2

Un autre moyen que d’utiliser: condition ? statement if true : statement if false est l’opérateur && (and):

Si à gauche de && est true alors ce qui est à droite est fait (retourne false si à droite c’est false). Si à gauche de && est faux alors ce qui est à droite est null ou n’est pas executé.

Prenons un exemple:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            unreadMessages: [
                "Call your mom!",
                "New spam email available. All links are definitely safe to click."
            ]
        }
    }

        render() {
        return (
            <div>
                <h2>You have {this.state.unreadMessages.length} unread messages!</h2>
            </div>
        )
    }
}

export default App
../_images/Capture434.PNG

Ce code affiche le nombre de message non lus. Quand il n’y pas de message ce code affiche quand même quelque chose :

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            unreadMessages: []
        }
    }
        render() {
        return (
            <div>
                <h2>You have {this.state.unreadMessages.length} unread messages!</h2>
            </div>
        )
    }
}

export default App
../_images/Capture2112.PNG

Lorsqu’il n’y pas de message on ne souhaiterait pas non plus être informé qu’il y 0 message (trop d’information tue l’information). D’après ce que l’on vient de voir dans la leçon précédente on peut écrire ceci comme cela:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            unreadMessages: []
        }
    }
    render() {
        return (
            <div>
                {
                    this.state.unreadMessages.length > 0 ?
                        <h2>You have {this.state.unreadMessages.length} unread messages!</h2> :
                        null
                }
            </div>
        )
    }
}

export default App
../_images/Capture3110.PNG

Qui n’affiche rien quand il y a zéro message.

On peut grâche à l’opérateur && réduire ce code comme cela:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            unreadMessages: []
        }
    }
    render() {
        return (
            <div>
                {
                    this.state.unreadMessages.length > 0 &&
                    <h2>You have {this.state.unreadMessages.length} unread messages!</h2>
                }
            </div>
        )
    }
}

export default App
../_images/Capture435.PNG

qui a le même résultat qu’avant.

En mettant trois messages on remarque que le message réapparaît avec trois messages non lus.

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            unreadMessages: ["a","b","c"]
        }
    }
    render() {
        return (
            <div>
                {
                    this.state.unreadMessages.length > 0 &&
                    <h2>You have {this.state.unreadMessages.length} unread messages!</h2>
                }
            </div>
        )
    }
}

export default App
../_images/Capture517.PNG

Conditional rendering Practice

import React from "react"

/*
Challenge:

Given a stateless functional component:
1. Follow the steps necessary to add state to it,
2. Have state keep of wheter the user is logged in or not
3. Add a button that logs the user in/out
   a. extra challenge - make the button display "log in" if they're not logged in and "log out" if
      they are
4. Display text that says "Logged in" if the user is logged in, or "Logged out" if they're not.
*/

function App() {
    return (
        <div>
            Code goes here
        </div>
    )
}

export default App

Hints:

Pour faire cet exercice, il nous faudra en 1) un class-base component et une méthode constructor. En 2) Il faudra un state avec une propriété d’objet booléene, appelons-là isLoggedIn (true or false). En 3) on ajoutera un even listener (onClick) et pour l’extra challenge on utilisera du Conditional Rendering. On appliquera aussi du Conditional Rendering au point 4).

import React from "react"

/*
Challenge:

Given a stateless functional component:
1. Follow the steps necessary to add state to it,
    // class-based component
    // constructor method
2. Have state keep of wheter the user is logged in or not
   // isLoggedIn: Boolean (true or false)
3. Add a button that logs the user in/out
   // event listener (onClick)
   a. extra challenge - make the button display "log in" if they're not logged in and "log out" if
      they are
          // Conditional Rendering
4. Display text that says "Logged in" if the user is logged in, or "Logged out" if they're not.
    // Conditional Rendering
*/

function App() {
    return (
        <div>
            Code goes here
        </div>
    )
}

export default App

Pour commencer il nous faut un class-based component car nous devons utiliser state. On remplace function par App et on enlève les parenthèses. Etant donné qu’il nous faudra introduire state nous devrons avoir la méthode constructor() suivi de super(). On initialise state qui est un objet avec une propriété isLoggedIn.

Donc voici pour les points 1) et 2)

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            isLoggedIn: false
        }
    }
    render() {
        return (
            <div>
                Code goes here
            </div>
        )
    }
}

export default App

Maintenant nous devons ajouter un bouton. Ensuite on ajoute un event listner pour permettre à notre button d’effectuer une action. Une méthode de classe nommée this.handClick est attribué à l’event listner. Créons la méthode de classe handlClick. “Bindons” la dans constructor(). Avant d’aller plus loin, il est bien de contrôler que tout fonctionne jusque là. Mettons un console.log pour vérifier cela:

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            isLoggedIn: false
        }
        this.handleClick=this.handleClick.bind(this)
    }
    handleClick(){
        console.log("I'm working")
    }

    render() {
        return (
            <div>
                <button onClick={this.handleClick}>LOG IN</button>
            </div>
        )
    }
}

export default App

et le résultat affiche bien ce que l’on veut quand on clique sur le bouton.

../_images/Capture436.PNG ../_images/Capture2113.PNG

Ce que l’on souhaite maintenant faire c’est de basculer la propriété isLoggedIn à true ou false suivant la donnée courante. On utilise setState pour ce faire, et comme on veut définir state en fonction de la valeur précédente, on utilisera une function. Pour afficher la nouvelle valeur de state on placera dans le render() le texte sur le bouton égale à l’inverse de isLoggedIn. On placera aussi un autre texte suivant que l’on est connecté ou pas. Pour placer ces textes on fera usage du Conditional Rendering :

import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            isLoggedIn: false
        }
        this.handleClick=this.handleClick.bind(this)
    }
    handleClick(){
        this.setState(prevState => {
            return {
                isLoggedIn: !prevState.isLoggedIn
            }
        })
    }

    render() {
        let buttonText = this.state.isLoggedIn ? "LOG OUT" : "LOG IN"
        let displayText= this.state.isLoggedIn ? "Logged in" : "Logged out"
        return (
            <div>
                <button onClick={this.handleClick}>{buttonText}</button>
                <h1>{displayText}</h1>
            </div>
        )
    }
}

export default App

Et le résultat:

../_images/Capture3112.PNG ../_images/Capture437.PNG

On voit bien que lorsque on clique sur le bouton l’état change impéccablement et le texte aussi.

Todo App - Phase 7

Reprenons notre exercice de Todo. Dans cette exercice nous allons appliquer un style lorsque la tâche a été effectuée. Comme mettre la ligne en italique, grisée, et biffée.

On utilise pour cela du inline styling. En fonction de la valeur de props.item.completed on choisira d’appliquer le style ou non. Voici le code :

/**
 * Challenge: Style the completed todo items differently from the incomplete items.
 */

import React from "react"

function TodoItem(props) {
    const completedStyle = {
        fontStyle: "italic",
        color: "#cdcdcd",
        textDecoration: "line-through"
    }

    return (
        <div className="todo-item">
            <input
                type="checkbox"
                checked={props.item.completed}
                onChange={() => props.handleChange(props.item.id)}
            />
            <p style={props.item.completed ? completedStyle: null}>{props.item.text}</p>
        </div>
    )
}

export default TodoItem 

Et un screenshot pour montrer le résultat :

../_images/Capture438.PNG

Fetching data from an API

Voici un lien pour l’explication de la comande fetch :

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch

La commande fetch renvoie une promise. Pour l’explication de promise voir le site suivant:

https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261

Dans cet exemple nous allons capturer les données de personnages du film Star Wars. Un site existe et se trouve à l’adresse suivante:

https://swapi.dev


import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {}
    }

    componentDidMount(){
        fetch("https://swapi.dev/api/people/1")
        .then(response => response.json())
        .then(data => console.log(data))
    }
    
    render() {
        return (
            <div>
                Code goes here
            </div>
        )
    }
}

export default App
../_images/Capture439.PNG

Pour enregistrer les données reçue par fetch nous allons les mettre dans state.

Voici le code pour ce faire:


import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            character: {}
        }
    }

    componentDidMount() {
        fetch("https://swapi.dev/api/people/1")
            .then(response => response.json())
            .then(data =>
                this.setState({
                    character: data
                })
            )
    }

    render() {
        return (
            <div>
                {this.state.character.name}
            </div>
        )
    }
}

export default App

Et le résultat:

../_images/Capture2114.PNG

Pour informer l’utilisateur que les données sont en cours de téléchargement on peut écrire un message d’information avec le code suivant:


import React from "react"

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            loading: false,
            character: {}
        }
    }

    componentDidMount() {
        this.setState({loading: true})
        fetch("https://swapi.dev/api/people/1")
            .then(response => response.json())
            .then(data =>
                this.setState({
                    loading: false,
                    character: data
                })
            )
    }

    render() {
        const text = this.state.loading ? "loading..." : this.state.character.name
        return (
            <div>
                <p>{text}</p>
            </div>
        )
    }
}

export default App

Le téléchargement est ici tellement rapide que l’on a à peine le temps de voir loading. Mais cela s’affiche correctement.

Forms Part 1

Un peu de théorie avant de se plonger dans le vif du sujet:

https://reactjs.org/docs/forms.html

La saisie dans un formulaire avec React déclenche un événement onChange qui modifie state après chaque caractère saisi. Pour illustrer ceci faisons un exemple d’une simple saisie d’un input.

import React, { Component } from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {}
    }

    render() {
        return (
            <form>
                <input type="text" placeholder="First Name" />
            </form>
        )
    }
}

export default App 

Pour voir chaque changement dans cette input box, on mettra un déclencheur onChange dans input box. Donc chaque fois que l’on changera la saisie dans l’input box on activera une fonction. Le but étant de changer state à chaque caractère saisi. Donc on doit prendre la valeur de input box et la passer à state. Pour l’instant state n’a pas de propriété à changer, mettons en un maintenant.

import React, { Component } from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {
            firstname: ""
        }
    }

    handChange(){

    }

    render() {
        return (
            <form>
                <input type="text" placeholder="First Name" onChange={this.handleChange} />
            </form>
        )
    }
}

export default App 

Etant donné que l’on ne se soucie pas de la valeur précédente de state on instanciera state de la manière suivante:

../_images/Capture440.PNG

et que doit-on mettre à la place des points d’interrogation? On sait que lors de déclenchement d’événement il y des paramètre prédéterminés qui sont transmis à la fonction. Nous allons donc mettre le paramètre event à notre fonction:

../_images/Capture2115.PNG

On trouve des informations importantes dans le paramètre event. Par exemple, on peut accéder à la valeur de notre input box.

../_images/Capture3113.PNG

event.target représente la source de l’événement déclenché ici c’est l’input box. Donc notre state est vraiment le reflet de la valeur saisie de notre input box.

pour voir la valeur de state mettons un h1 pour voir le résultat:

../_images/Capture442.PNG

On voit que rien de s’affiche. C’est parce que nous n’avons pas binder notre handleChange. Il faut mettre la commande suivante dans le constructor()

../_images/Capture518.PNG

Et maintenant on voit que ça fonctionne:

../_images/Capture618.PNG

Maintenant au lieu d’avoir qu’une seule valeur dans notre formulaire, mettons en plusieurs:

import React, { Component } from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {
            firstName: "",
            lastName: ""
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        this.setState({
            firstName: event.target.value
        })
    }

    render() {
        return (
            <form>
                <input type="text" placeholder="First Name" onChange={this.handleChange} />
                <br />
                <input type="text" placeholder="Last Name" onChange={this.handleChange} />
                <h1>{this.state.firstName} {this.state.lastName}</h1>
            </form>
        )
    }
}

export default App 
../_images/Capture716.PNG

Le résultat n’est pas vraiment satisfaisant car il efface First Name dès que l’on commence à tapez quelque chose dans Last Name.

Pour parer à celon nous pourrions très bien faire une fonction pour chaque entrée d’un formulaire comme par exemple handleChangeLastName. Mais cela ne sera pas très simple lorsque le formulaire aura beaucoup de champs.

Au lieu de cela nous n’allons pas coder en dur firstName ici:

../_images/Capture814.PNG

Mais donner un nom de propriété à notre input box:

../_images/Capture914.PNG

et aussi apporter le changement suivant à notre fonction handleChange():

../_images/Capture1013.PNG

On voit que ça fonctionne bien:

../_images/Capture1112.PNG

Encore une chose pour améliorer on ajoute value à notre input box:

../_images/Capture1212.PNG

et lorsque la ligne devient longue on peut mettre chaque attribut sur une ligne :

../_images/Capture1312.PNG

De cette manière on force la value à ce qu’est state.

Une autre chose pour simplifier le déboggage et pour rendre plus lisible le code:

../_images/Capture1412.PNG

Et pour clore cette section le code de App.js en entier:

import React, { Component } from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {
            firstName: "",
            lastName: ""
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        const {name, value} = event.target
        this.setState({
            [name]: value
        })
    }

    render() {
        return (
            <form>
                <input
                    type="text"
                    value={this.state.firstName}
                    name="firstName"
                    placeholder="First Name"
                    onChange={this.handleChange} />
                <br />
                <input
                    type="text"
                    value={this.state.lastName}
                    name="lastName"
                    placeholder="Last Name"
                    onChange={this.handleChange} />
                <h1>{this.state.firstName} {this.state.lastName}</h1>
            </form>
        )
    }
}

export default App 

Forms Part 2

Nous allons introduire maintenant les différents éléments utiles que peuvent contenir les éléments de formulaires qui sont:

  • <textarea /> element

  • <input type=”checkbox” />

  • <input type=”radio” />

  • <select> and <option> elements

textarea

En html, textarea n’a pas de self closing tag comme input mais comporte un closing tag:

<textarea></textarea>
../_images/Capture443.PNG

Que l’on peut étendre dans la page web. L’utilisateur a aussi la possibilité de mettre un largeur et un hauteur fixe.

En React, il n’y a pas de closing tag. Ca reprend la même philosophie que input et est plus consistent.

../_images/Capture1103.PNG ../_images/Capture2116.PNG
input type= checkbox

Il n’y pas de propriété value comme utilisé avec type text ou textarea. Il faut penser que sa propriété est checked ou pas. Cela veut dire que l’on va mettre un propriété checked:

../_images/Capture3114.PNG

Et ceci va faire entrer la notion d’une propriété Bolean. Donc checkbox maintiennent des valeurs booléennes dans state. Pour l’exemple, mettons:

../_images/Capture444.PNG

Déclarons cette valeur dans state:

../_images/Capture519.PNG ../_images/Capture619.PNG

On remarque que la page ne nous permet pas de déchecké. Ceci est normal car nous avons mis la propriété à true par state. Pour pouvoir être en mesure de déchecker on va rajouter la propriété onChange et un name:

../_images/Capture717.PNG

et mettons un peu en forme:

../_images/Capture815.PNG

Maintenant la partie tricky: dans une input box on trace ce qui à été tapez. Rappelez vous dans le handleChange on traçait par value pour la mise à jour de state. Dans une check box il n’y a pas de value mais une propriété checked et cette propriété va retourner soit vraie ou false. Ce que nous aurons besoins pour maintenir notre handleChange, c’est savoir si notre élément de notre formulaire est une checkbox ou pas. Nous devrons tirer de event.target le type et checked:

../_images/Capture915.PNG

Parce que une checkbox n’a pas value nous ne pourrons pas executer le code:

../_images/Capture1014.PNG

mais nous voudrons changer [name] qui est friendly et lui assigner la valeur checked:

../_images/Capture1113.PNG

Et là nous pouvons déchecker:

../_images/Capture1213.PNG

Pour enlever le warning pour textarea mettons aussi un handleChange:

../_images/Capture1313.PNG
radio button

Les bouton radio sont une combinaison entre input type text et input type check box. Ce que l’on entend par là c’est qu’il va utiliser la propriété value et la propriété checked.

Construisons deux boutons radios un pour female et un autre pour male:

../_images/Capture1413.PNG

On remarque que lorsque que Is friendly n’est pas coché on ne peut pas activer ni pour Male ni pour Female. Ceci est dû au fait que l’on a repris le state de isFriendly. Se qui provoque des comportemenents étranges. Mettons à la place:

../_images/Capture1512.PNG

Et déclarons:

../_images/Capture1612.PNG

Voici le résultat:

../_images/Capture1710.PNG

Le programme enregistre ces valeurs que l’on peut illustrer:

../_images/Capture1810.PNG

et le résultat:

../_images/Capture1910.PNG ../_images/Capture2010.PNG

Il est claire que du premier abord ceci paraît bien compliqué, ceci n’a pas lieu d’être mémorisé, il suffit de reprendre des exemples. Il existe un librairie Formik facilitant la tâche.

select box

React heureusement maintient la propriété value par exemple si l’on veut une liste de notre couleur préférée:

../_images/Capture2117.PNG

La valeur que l’on choisira dans option sera transmise à state.favColor

Déclarons cette propriété dans state:

../_images/Capture2210.PNG

mettons aussi handleChange et name pour être sûr que ça coïncide avec notre propriété de state, les valeurs de options doivent être remplies:

../_images/Capture2310.PNG

et le résultat:

../_images/Capture2410.PNG

Ce qui cool avec react c’est que tout les éléments peuvent être activés par une seule fonction handlChange. Check box doit juste être testée avec une condition if (ou ? … : …).

Pour le summit button, html5 gère ça très bien: quand il trouve button dans un form il l’associera automatiquement à un summit button. Dès que l’utilisateur appuiera sur ce bouton l’événment onSumit du formulaire sera déclenché.

Voici le app.js:

import React, { Component } from "react"

class App extends Component {
    constructor() {
        super()
        this.state = {
            firstName: "",
            lastName: "",
            isFriendly: true,
            gender: "",
            favColor: "blue"
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        const { name, value, type, checked } = event.target
        type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value })
    }

    render() {
        return (
            <form>
                <input
                    type="text"
                    value={this.state.firstName}
                    name="firstName"
                    placeholder="First Name"
                    onChange={this.handleChange} />
                <br />
                <input
                    type="text"
                    value={this.state.lastName}
                    name="lastName"
                    placeholder="Last Name"
                    onChange={this.handleChange} />
                {
                    /**
                     * Othewr useful form elements:
                     */
                }

                <textarea
                    value={"Some default value"}
                    onChange={this.handleChange}
                />
                <br />
                <label>
                    <input
                        type="checkbox"
                        name="isFriendly"
                        checked={this.state.isFriendly}
                        onChange={this.handleChange}
                    /> Is friendly?
                </label>
                <br />
                <label>
                    <input
                        type="radio"
                        name="gender"
                        value="male"
                        checked={this.state.gender === "male"}
                        onChange={this.handleChange}
                    /> Male
                </label>
                <br />
                <label>
                    <input
                        type="radio"
                        name="gender"
                        value="female"
                        checked={this.state.gender === "female"}
                        onChange={this.handleChange}
                    /> Female
                </label>
                {/*Formik*/}
                <br />

                <label>Favorite Color:</label>
                <select value={this.state.favColor}
                    onChange={this.handleChange}
                    name="favColor"
                >
                    <option value="blue">Blue</option>
                    <option value="green">Green</option>
                    <option value="red">Red</option>
                    <option value="orange">Orange</option>
                    <option value="yellow">Yellow</option>
                </select>

                <h1>{this.state.firstName} {this.state.lastName}</h1>
                <h2>You are a {this.state.gender}</h2>
                <h2>Your favorite color is {this.state.favColor}</h2>
            </form>
        )
    }
}

export default App 

Forms Practice

Voici un exercice sur les Forms: la consigne se trouve à l’intérieur du fichier Apps.js

import React, { Component } from "react"

/**
 * Challenge: Wire up the partially-finished travel form so that it works!
 * Remember to use the concept of controlled forms
 * https://reactjs.org/docs/forms.html
 * 
 * All information should be populating the text below the form in real-time
 * as you're filling it out
 * 
 * This exercice is adapted from th V School curriculum on vanilla JS forms:
 * https://coursework.vschool.io/travel-form/
 * 
 * All of our challenges and learning ressources are opne for the public
 * to play around with and learn from at https://coursework.vschool.io
 */

class App extends Component {
    constructor() {
        super()
        this.state = {}
    }

    render() {
        return (
            <main>
                <form>
                    <input placeholder="First Name" /><br />
                    <input placeholder="Last Name" /><br />
                    <input placeholder="Age" /><br />

                    {/* Create radio buttons for gender here */}
                    <br />

                    {/* Create select box for location here */}
                    <br />

                    {/* Create check boxes for dietary restrictions here */}
                    <br />

                    <button>Submit</button>
                </form>
                <hr />
                <h2>Entered information:</h2>
                <p>Your name: {/* First and last name here */}</p>
                <p>Your age: {/* Age here */}</p>
                <p>Your gender: {/* Gender here */}</p>
                <p>Your destination: {/* Destination here */}</p>
                <p>
                    Your dietary restrictions:
            {/* Dietary restrictions here, comma separated */}
                </p>
            </main>
        )
    }
}

export default App 

Il y plusieurs manières d’aborder cet exercice. Tout d’abord nous allons initialiser tout ce qu’il y a à l’intérieur de state:

Remarques:

La propriété age mettons-la à 0 pour l’instant. La location sera sous la propriété destination. Une check box pour dietaryRestrictions. Il y aura en fait plusieurs check boxes car on peut très bien être allergique à plusieurs ingrédients. C’est pourquoi nous l’initialiserons avec un tableau.

../_images/Capture445.PNG

Maintenant que nous avons initialisé ce qu’il y a dans state, nous allons remplir les éléments existant dans les input donnée dans le fichier Apps.js faisant office de consigne.

Nous savons que nous aurons besoin d’une propriété name pour chaque input et d’une value déterminée par state (this.state.???). Chaque input sera aussi sujet au changement (onChange=…) qui appellera probablement handleChange. Attention les trois figures suivantes le nom de handChange a mal été orthographié, c’est en fait handleChange.

../_images/Capture2118.PNG

Pour plus de lisibilité mettons cela sur plusieurs lignes:

../_images/Capture3115.PNG

Attribuons maintenant à name les propriétés de state respectivement, complétons aussi this.state. … avec les mêmes noms:

../_images/Capture446.PNG

Avant que nous poursuivons par rajouter des éléments, occupons-nous de handleChange et ne pas oublier le bind:

../_images/Capture520.PNG

Descendons maintenant pour voir si ces trois inputs fonctionnenet correctement:

../_images/Capture620.PNG ../_images/Capture718.PNG

Jusque-là tout à l’air fonctionner mais essayer d’initialiser la propriété age à null et le navigateur grogne. Mettons la à un empty string est ça a l’air mieux.

Occupons-nous de notre gender, il est bien de le mettre entre un label. On se rappelle radio button possède une value, name et une propriété checked. Et celui-ci est un peu tricky lorsque celui-ci est male alors il sera checked.

../_images/Capture816.PNG

Copions ce bribe de code pour female:

../_images/Capture916.PNG ../_images/Capture1015.PNG

Parfait on peut sélectionner male ou female.

Mettons encore ceci à l’affichage de gender.

Occupons-nous de select box pour Destination.

select box contiendra 4 options car ce n’est pas une grande compagnie aérienne.

Chaque option prendra une propriété value. Les valeurs de nos options sont en fait les valeurs que state devrait être si une de ces options a été choisie. Ce sont en fait nos différentes locations. Mettons ces valeurs en minuscule pour que l’on soit consistent avec le reste. La valeur value de select est la valeur choisie. Et comme les autres, soyons sûr qu’il comporte un name qui match avec la propriété dans state. Et comme d’habitude onChange. Et dans la partie display on met la destination.

../_images/Capture1114.PNG ../_images/Capture1214.PNG

On remarque que Germany est affiché dans la liste par défault et que dans le display il ne s’affiche pas. Pour en fait sélectionner Germany il faudra d’abord sélectionner un autre pays et séléctionner Germany. Pour parer à ce défaut, on affichera par défault un autre texte:

../_images/Capture1314.PNG ../_images/Capture1414.PNG

Ok, nous avons gardé le plus difficile pour la fin et c’est nos checked box. Souvenons-nous lors de l’initialisation de nos propriété de state, nous avions mis un tableau vide pour dietaryRestrictions. En fait il sera plus facille de créer un sous objet et une valeur booléene pour chaque dietaryRestriction.

../_images/Capture1513.PNG

Nous aurons donc trois check boxes. Englobons check box dans un label. type sera à “checkbox”, name à la valeur de notre propriété de state comme isVegan, onChange l’événement déclenchant handleChange, checked qui sera égal à une propriété nested. Le text de label sera Vegan? Copions ceci et remplaçons avec les autres restrictions culinaires.

../_images/Capture1613.PNG

Vous noterez que nous ne sommes pas en mesure de checker ces checkboxes. Les checkbox n’a pas de propriété value et handleChange ne peut modifier que les propriétés value. Nous devons d’abord contrôler si le type une checkbox, donc nous devons tirer de event: type et checked. On ne peut pas simplement dire que [name]: checked, car nous avons choisi d’avoir un nested object. Pour une raison que je ne saurai expliquer le concept de nested object doit être oublié. Mais peut être une piste pourquoi ça ne marche pas c’est peut-être dû au fait que changer un nested object les autres propriété de state ne se mettent pas à jour. Comme workaround nous allons supprimé notre subobject : dietaryRestrictions. Et mettre chaque élément comme une propriété de state.

../_images/Capture1712.PNG

et modifions encore:

../_images/Capture1812.PNG

et là ça a l’air de marcher:

../_images/Capture1912.PNG

Complétons encore le display:

../_images/Capture2012.PNG

On remarque que lorsque l’on coche restriction, React n’affiche pas de boléen.

../_images/Capture2119.PNG

On peut écrire le code suivant pour une bon affichage:

../_images/Capture2212.PNG

et le résultat final :

../_images/Capture2312.PNG
import React, { Component } from "react"

/**
 * Challenge: Wire up the partially-finished travel form so that it works!
 * Remember to use the concept of controlled forms
 * https://reactjs.org/docs/forms.html
 * 
 * All information should be populating the text below the form in real-time
 * as you're filling it out
 * 
 * This exercice is adapted from th V School curriculum on vanilla JS forms:
 * https://coursework.vschool.io/travel-form/
 * 
 * All of our challenges and learning ressources are opne for the public
 * to play around with and learn from at https://coursework.vschool.io
 */

class App extends Component {
    constructor() {
        super()
        this.state = {
            firstName: "",
            lastName: "",
            age: "",
            gender: "",
            destination: "",
            isVegan: false,
            isKosher: false,
            isLactoseFree: false
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        const { name, value, type, checked } = event.target
        type === "checkbox" ?
            this.setState({
                [name]: checked
            })
            :
            this.setState({
                [name]: value
            })
    }

    render() {
        return (
            <main>
                <form>
                    <input
                        name="firstName"
                        value={this.state.firstName}
                        onChange={this.handleChange}
                        placeholder="First Name"
                    />
                    <br />

                    <input
                        name="lastName"
                        value={this.state.lastName}
                        onChange={this.handleChange}
                        placeholder="Last Name"
                    />
                    <br />

                    <input
                        name="age"
                        value={this.state.age}
                        onChange={this.handleChange}
                        placeholder="Age"
                    />
                    <br />

                    <label>
                        <input
                            type="radio"
                            name="gender"
                            value="male"
                            checked={this.state.gender === "male"}
                            onChange={this.handleChange}
                        /> Male
                    </label>

                    <br />

                    <label>
                        <input
                            type="radio"
                            name="gender"
                            value="female"
                            checked={this.state.gender === "female"}
                            onChange={this.handleChange}
                        /> Female
                    </label>

                    <br />

                    <select
                        value={this.state.destination}
                        name="destination"
                        onChange={this.handleChange}
                    >
                        <option value="">-- Please Choose a destination --</option>
                        <option value="germany">Germany</option>
                        <option value="norway">Norway</option>
                        <option value="north pole">North Pole</option>
                        <option value="south pole">South Pole</option>
                    </select>

                    <br />

                    <label>
                        <input
                            type="checkbox"
                            name="isVegan"
                            onChange={this.handleChange}
                            checked={this.state.isVegan}
                        /> Vegan?
                    </label>

                    <br />

                    <label>
                        <input
                            type="checkbox"
                            name="isKosher"
                            onChange={this.handleChange}
                            checked={this.state.isKosher}
                        /> Kosher?
                    </label>

                    <br />

                    <label>
                        <input
                            type="checkbox"
                            name="isLactoseFree"
                            onChange={this.handleChange}
                            checked={this.state.isLactoseFree}
                        /> Lactose Free?
                    </label>

                    <br />

                    <button>Submit</button>
                </form>
                <hr />
                <h2>Entered information:</h2>
                <p>Your name: {this.state.firstName} {this.state.lastName}</p>
                <p>Your age: {this.state.age}</p>
                <p>Your gender: {this.state.gender}</p>
                <p>Your destination: {this.state.destination}</p>
                <p>Your dietary restrictions:</p>
                <p>Vegan : {this.state.isVegan ? "Yes" : "No"}</p>
                <p>Kosher : {this.state.isKosher ? "Yes" : "No"}</p>
                <p>Lactose Free : {this.state.isLactoseFree ? "Yes" : "No"}</p>
            </main >
        )
    }
}

export default App 

Container/Component Architecture

Notre exemple d’avant possède beaucoup de ligne et il est pas facile de trouver la bonne ligne. On voit qu’une partie s’occupe de la display logique en particulier ce qu’il y dans le render. Une autre partie contient les state et le business logique comme handleChange. Il serait très judicieux de segmenter notre code en partie comme la UI logique ou la rendering Logique et la Business logique qui en fait commande la rendering Logique. Le but c’est d’avoir un component qui maintient state et la méthode qui update state et un autre component dédié à UI logique ou presentation logique appelé presentational component. Qui aura la seule tache de recevoir props pour un affichage correcte.

Un petit lien pour lire:

https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

Analysons maintenant le code vu précédemment. Tout notre code est maintenu dans un seul composant App. En réalité on veut que notre App render notre form et que form fasse tout les formy things. Créons un nouveau component appelé Form.js et copions tout le contenu de App.js dans Form.js. Changeons le nom App en Form et export default Form. Revenons dans App.js et importons Form. Comme Form s’occupe au rendu de notre formulaire on peut en faire un functional component.

../_images/Capture1104.PNG

Et l’on voit que notre app fonctionne toujours. On se rappelle que App est comme une table des matières comportant par exemple un header, main et un footer.

Pour l’instant nous avons tout dans Form. Nous allons créer un nouveau component appelé FormComponent.js Pour plus de consistence renommons Form.js en FormContainer.js et updatons App.js avec ce nom.

../_images/Capture2120.PNG

Dans le FormContainer coupons tout la render logique. Ensuite dans le component FormComponent rajoutons:

../_images/Capture3116.PNG

et copions en-dessous ce que nous avons coupé.

On remarque que l’app ne fonctionne plus c’est parce que nous avons coupé ce que qu’il y avait dans un class component dans un functionnal component.

Nous avons this.state.firstName et this.handleChange cette functionnal component n’a pas de handleChange méthode et n’a pas de state. En fait elle va recevoir tout par props. Nous reviendrons dans une minute pour fixer cela.

Dans notre FormContainer nous avons maintenant un render() vide. Ce que nous allons faire c’est que FormContainer dedicate tout le UI stuff au FormComponent. Donc à l’entente nous allons importer FormComponent. Et render simplement <FormComponent />

../_images/Capture447.PNG

Bien entendu nous devrons faire passer tout un tas de props. Mais déjà nous pouvons voir que la structure est devenue plus simple. Donc nous devons faire passer state et handleChange. Passons d’abord handleChange :

../_images/Capture522.PNG

Maintenant dans le composant FormComponent partout où il y this.handleChange nous devons le remplacer par props.handleChange.

../_images/Capture622.PNG

Pour state nous pourrions passez tout les propriétés par firstName={this.state.firstName etc… mais cela va rajouter plein de ligne à la suite de <FormComponent. Une autre option qui s’offre à nous est d’utiliser un objet appelé data={this.state}

../_images/Capture719.PNG

et modifions FormComponent:

../_images/Capture817.PNG

remettons return() car nous l’avions couper dans FormContainer et rajouter dans FormComponent: import React

Et l’app refonctionne.

Voici le fichier App.js:

import React, { Component } from "react"
import FormContainer from "./FormContainer"

function App() {
    return (
        <FormContainer />
    )
} 

export default App 

Voici le fichier FormContainer.js:

import React, { Component } from "react"
import FormComponent from "./FormComponent"

class FormContainer extends Component {
    constructor() {
        super()
        this.state = {
            firstName: "",
            lastName: "",
            age: "",
            gender: "",
            destination: "",
            isVegan: false,
            isKosher: false,
            isLactoseFree: false
        }
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(event) {
        const { name, value, type, checked } = event.target
        type === "checkbox" ?
            this.setState({
                [name]: checked
            })
            :
            this.setState({
                [name]: value
            })
    }

    render() {
        return(
        <FormComponent
            handleChange={this.handleChange}
            data={this.state}
        />
        )
    }
}

export default FormContainer

Voici le fichier FormComponent.js:

import React from "react"

function FormComponent(props) {
    return (
        <main>
            <form>
                <input
                    name="firstName"
                    value={props.data.firstName}
                    onChange={props.handleChange}
                    placeholder="First Name"
                />
                <br />

                <input
                    name="lastName"
                    value={props.data.lastName}
                    onChange={props.handleChange}
                    placeholder="Last Name"
                />
                <br />

                <input
                    name="age"
                    value={props.data.age}
                    onChange={props.handleChange}
                    placeholder="Age"
                />
                <br />

                <label>
                    <input
                        type="radio"
                        name="gender"
                        value="male"
                        checked={props.data.gender === "male"}
                        onChange={props.handleChange}
                    /> Male
            </label>

                <br />

                <label>
                    <input
                        type="radio"
                        name="gender"
                        value="female"
                        checked={props.data.gender === "female"}
                        onChange={props.handleChange}
                    /> Female
            </label>

                <br />

                <select
                    value={props.data.destination}
                    name="destination"
                    onChange={props.handleChange}
                >
                    <option value="">-- Please Choose a destination --</option>
                    <option value="germany">Germany</option>
                    <option value="norway">Norway</option>
                    <option value="north pole">North Pole</option>
                    <option value="south pole">South Pole</option>
                </select>

                <br />

                <label>
                    <input
                        type="checkbox"
                        name="isVegan"
                        onChange={props.handleChange}
                        checked={props.data.isVegan}
                    /> Vegan?
            </label>

                <br />

                <label>
                    <input
                        type="checkbox"
                        name="isKosher"
                        onChange={props.handleChange}
                        checked={props.data.isKosher}
                    /> Kosher?
            </label>

                <br />

                <label>
                    <input
                        type="checkbox"
                        name="isLactoseFree"
                        onChange={props.handleChange}
                        checked={props.data.isLactoseFree}
                    /> Lactose Free?
            </label>

                <br />

                <button>Submit</button>
            </form>
            <hr />
            <h2>Entered information:</h2>
            <p>Your name: {props.data.firstName} {props.data.lastName}</p>
            <p>Your age: {props.data.age}</p>
            <p>Your gender: {props.data.gender}</p>
            <p>Your destination: {props.data.destination}</p>
            <p>Your dietary restrictions:</p>
            <p>Vegan : {props.data.isVegan ? "Yes" : "No"}</p>
            <p>Kosher : {props.data.isKosher ? "Yes" : "No"}</p>
            <p>Lactose Free : {props.data.isLactoseFree ? "Yes" : "No"}</p>
        </main >
    )
}

export default FormComponent
../_images/Capture817.PNG

Meme Generator Capstone Project

Create the boilerplate to get React to render something on the screen Render an <App /> component, which you’ll need to create separately

Voici le fichier index.js:

 import React from "react"
 import ReactDOM from "react-dom"
 import App from "./App"

 ReactDOM.render(<App />, document.getElementById("root"))

Voici le fichier App.js:

import React from "react"

function App() {
    return (
        <h1>Hello!</h1>
    )
}

export default App

Create 2 new components - Header and MemeGenerator Header will only display things MemeGenerator will be calling to an API and holding on to data Each should be in their own file of the same name.

../_images/Capture1105.PNG ../_images/Capture2122.PNG ../_images/Capture3117.PNG ../_images/Capture448.PNG

Commençons à changer le header:

../_images/Capture523.PNG ../_images/Capture623.PNG

Voilà c’est gentiment tout ce que l’on va apporter au component Header. On remarque qu’il est responsive.

Occupons-nous de MemeGenerator:

Initialize state to save the following data:

../_images/Capture720.PNG

We’ll be using an API that provides a bunch of meme images.

Your task: make an API call to “https://api.imgflip.com/get_memes” and save the data that comes back (response.data.memes) to a new state property called allMemeImgs. (The data that comes back is an array)

../_images/Capture818.PNG ../_images/Capture917.PNG

Parfait cela nous renvoit un objet avec plusieurs propriété. Celle qui va nous intéresser est l’url.

A la place de <h1>MEME GENERATOR SECTION</h1>, nous allons mettre un controlled form. Voici l’énoncé de l’exercice:

Create 2 input fields, one for the topText and one for the bottomText. Remember that these will be “controlled forms”, so make sure to add all the attributes you’ll need for that to work

../_images/Capture1016.PNG

Create the onChange handler method. It should update the corresponding state on every change of the input box.

../_images/Capture1115.PNG

Ne pas oublier le bind à placer dans constructor()

../_images/Capture1215.PNG

La prochaine étape est placé à un endroit notre meme. Rappeler nous recevons dans un tableau tout les meme que cet API possède. Et ce que nous allons implanté c’est que lorsque l’utilisateur appuie sur le bouton GEN, un meme est choisi au hasard. Pour l’afficher dans une air en dessous. Nous allons construire cette air maintenant.

../_images/Capture1315.PNG ../_images/Capture1415.PNG

Create a method that,when the “Gen” button is clicked, chooses one of the memes from our àllMemeImgs` array at random and makes it so that is the meme image that shows up in the bottom portion of our meme generator site.

On pourrait très bien mettre un onClick sur notre button, mais comme il est à l’intérieur d’un form, je préfère mettre un onSubmit sur le form.

../_images/Capture1514.PNG

Créons le handleSubmit avec even en paramètre because we don’t prevent the default parce que nous ne voulons pas toujours rafraîchir notre page. (j’ai rien compris mais bon…). N’oublions pas de binder cette nouvelle méthode. Décrivons les étapes de cette méthode:

  • get a random int (index in the array)

  • get the meme from that index

  • set randomImg to the .url of the random item

../_images/Capture1614.PNG

Et en cliquant sur GEN une image aléatoire s’affiche

../_images/Capture1713.PNG

Et les codes:

MemeGenerator.js:

import React, { Component } from "react"

class MemeGenerator extends Component {
    constructor() {
        super()
        this.state = {
            topText: "",
            bottomText: "",
            randomImg: "http://i.imgflip.com/1bij.jpg",
            allMemeImgs: []
        }
        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)

    }

    componentDidMount() {
        fetch("https://api.imgflip.com/get_memes")
            .then(response => response.json())
            .then(response => {
                const { memes } = response.data
                this.setState({ allMemeImgs: memes })
            })
    }

    handleChange(event) {
        const { name, value } = event.target
        this.setState({
            [name]: value
        })
    }

    handleSubmit(event) {
        event.preventDefault()
        const randNum = Math.floor(Math.random() * this.state.allMemeImgs.length)
        const randMemeImg = this.state.allMemeImgs[randNum].url
        this.setState({ randomImg: randMemeImg })
    }

    render() {
        return (
            <div>
                <form className="meme-form" onSubmit={this.handleSubmit}>
                    <input
                        type="text"
                        value={this.state.topText}
                        name="topText"
                        placeholder="Top Text"
                        onChange={this.handleChange}
                    />
                    <input
                        type="text"
                        value={this.state.bottomText}
                        name="bottomText"
                        placeholder="Bottom Text"
                        onChange={this.handleChange}
                    />
                    <button>Gen</button>
                </form>
                <div className="meme">
                    <img src={this.state.randomImg} alt="" />
                    <h2 className="top">{this.state.topText}</h2>
                    <h2 className="bottom">{this.state.bottomText}</h2>
                </div>
            </div>
        )
    }
}
export default MemeGenerator

Header.js:

import React from "react"

function Header() {
    return (
        <header>
            <img
                src="http://www.pngall.com/wp-content/uploads/2016/05/Trollface.png"
                alt="Problem?"
            />
        </header>
    )
}

export default Header

style.css:

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    background-color: whitesmoke;
}

header {
    height: 100px;
    display: flex;
    align-items: center;
    background: #6441A5;  /* fallback for old browsers */
    background: -webkit-linear-gradient(to right, #2a0845, #6441A5);  /* Chrome 10-25, Safari 5.1-6 */
    background: linear-gradient(to right, #2a0845, #6441A5); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}

header > img {
    height: 80%;
    margin-left: 10%;
}

header > p {
    font-family: VT323, monospace;
    color: whitesmoke;
    font-size: 50px;
    margin-left: 60px;
}

.meme {
    position: relative;
    width: 90%;
    margin: auto;
}

.meme > img {
    width: 100%;
}

.meme > h2 {
    position: absolute;
    width: 80%;
    text-align: center;
    left: 50%;
    transform: translateX(-50%);
    margin: 15px 0;
    padding: 0 5px;
    font-family: impact, sans-serif;
    font-size: 2em;
    text-transform: uppercase;
    color: white;
    letter-spacing: 1px;
    text-shadow:
        2px 2px 0 #000,
        -2px -2px 0 #000,
        2px -2px 0 #000,
        -2px 2px 0 #000,
        0 2px 0 #000,
        2px 0 0 #000,
        0 -2px 0 #000,
        -2px 0 0 #000,
        2px 2px 5px #000;
}

.meme > .bottom {
    bottom: 0;
}

.meme > .top {
    top: 0;
}

.meme-form {
    width: 90%;
    margin: 20px auto;
    display: flex;
    justify-content: space-between;
}

.meme-form > input {
    width: 45%;
    height: 40px;
}

.meme-form > button {
    border: none;
    font-family: VT323, monospace;
    font-size: 25px;
    letter-spacing: 1.5px;
    color: white;
    background: #6441A5;
}

.meme-form > input::-webkit-input-placeholder { /* Chrome/Opera/Safari */
  font-family: VT323, monospace;
  font-size: 25px;
  text-align: cen
}
.meme-form > input::-moz-placeholder { /* Firefox 19+ */
  font-family: VT323, monospace;
  font-size: 25px;
  text-align: cen
}
.meme-form > input:-ms-input-placeholder { /* IE 10+ */
  font-family: VT323, monospace;
  font-size: 25px;
  text-align: cen
}
.meme-form > input:-moz-placeholder { /* Firefox 18- */
  font-family: VT323, monospace;
  font-size: 25px;
  text-align: cen
}

Writing Modern React Apps

Dans cette section nous allons voir comment écrire quelques lignes de façon plus moderne.

En fait on peut écrire nos méthodes de classe en arrow function: par exemple notre méthode handleChange: le changement à l’air très petit mais nous permet de supprimer le bind.

../_images/Capture1106.PNG ../_images/Capture2123.PNG

Aussi on peut créer directement des variables de classe. Sans que l’on ait à créer un constructor.

../_images/Capture3118.PNG ../_images/Capture449.PNG

Voici quelques liens vers des nouveautés de React:

Smiley Face

source : https://www.youtube.com/watch?v=2LhoCfjm8R4&t=15506s

../_images/Capture1107.PNG

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Smiley Face Part I</title>
    <style>
      body {
        margin: 0; 
        overflow: hidden;
      }
    </style>
    <script src="https://unpkg.com/react@16.9.0/umd/react.production.min.js"></script> 
    <script src="https://unpkg.com/react-dom@16.9.0/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/d3@6.6.0/dist/d3.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>

index.js

import React from 'react';
import ReactDOM from 'react-dom';


import {Face} from './Face'

const width = 960;
const height = 500;


 const App = () => (
  <Face
    width = {width}
    height = {height}
    centerX = {width/2}
    centerY = {height/2}
    strokeWidth = {20}
    eyeOffsetX = {100}
    eyeOffsetY = {100}
    eyeRadius = {40}
    mouthWidth = {20}
    mouthRadius = {140}
    />
 );

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);

Face.js

import {BackgroundCircle} from './BackgroundCircle'
import {Eyes} from './Eyes'
import {Mouth} from './Mouth'
import {FaceContainer} from './FaceContainer'

export const Face = ({
  width,
  height,
  centerX,
  centerY,
  strokeWidth,
  eyeOffsetX,
  eyeOffsetY,
  eyeRadius,
  mouthWidth,
  mouthRadius
  }) => (
   <FaceContainer
     width={width}
     height={height}
     centerX={centerX}
     centerY={centerY}
   >
     <BackgroundCircle 
       radius={centerY-strokeWidth/2}
       strokeWidth={strokeWidth}
     />
     <Eyes
       eyeOffsetX={eyeOffsetX}
       eyeOffsetY={eyeOffsetY}
       eyeRadius={eyeRadius}
     />
     <Mouth 
       mouthWidth={mouthWidth}
       mouthRadius={mouthRadius}
     />
   </FaceContainer>
  );

FaceContainer.js

export const FaceContainer = ({children, width, height, centerX, centerY}) => (
  <svg width={width} height={height}>
    <g transform={`translate(${centerX},${centerY})`}>
      {children}
    </g>  
	</svg>
  );

BackgroundCircle.js

export const BackgroundCircle = ({radius, strokeWidth}) => (
  <circle 
        r={radius} 
        fill="yellow"
        stroke="black"
        stroke-width={strokeWidth}
  />
);

Eyes.js

export const Eyes = ({eyeOffsetX,eyeOffsetY,eyeRadius}) => (
  <>
    <circle 
      cx={-eyeOffsetX} 
      cy={-eyeOffsetY}
      r={eyeRadius}
    />
    <circle 
      cx={eyeOffsetX} 
      cy={-eyeOffsetY}
      r={eyeRadius}
    />
  </>
);

Mouth.js

import { arc } from 'd3';

export const Mouth = ({mouthWidth, mouthRadius}) => {
  const mouthArc = arc()
  .innerRadius(mouthRadius)
  .outerRadius(mouthRadius + mouthWidth)
  .startAngle(Math.PI / 2)
  .endAngle(Math.PI * 3/2);
  return <path d={mouthArc()}/> 
};

Mouse Follower

A circle that follows a circle.

source : https://www.youtube.com/watch?v=2LhoCfjm8R4&t=15506s

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Mouse Follower</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
    </style>
    <script src="https://unpkg.com/react@16.9.0/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16.9.0/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/d3@5.11.0/dist/d3.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>

index.js

import React, {useState, useCallback} from 'react';
import ReactDOM from 'react-dom';

const width = 960;
const height = 500;
const circleRadius = 30;
const initialMousePosition = {x: width / 2, y: height / 2};



const App = () => {
  const [mousePosition, setMousePosition]=useState(initialMousePosition);
  const handleMouseMove = useCallback(event => {
  const { clientX, clientY} = event;
  setMousePosition({x: clientX, y: clientY})
},[setMousePosition]);
  return (
    <svg width={width} height={height} onMouseMove={handleMouseMove}>
      <circle
        cx={mousePosition.x}
        cy={mousePosition.y}
        r={circleRadius}
      />
    </svg>
  );
};

const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);

Working with .xml

JavaScript Tip: Loading XML Data Using Fetch

https://www.youtube.com/watch?v=0gON4MUdJE8

JavaScript Question: How do I Work with XML Data?

https://www.youtube.com/watch?v=Fkw_OlcLcwE

Good videos to learn

2.3 HTTP Post Request with fetch() - Working with Data and APIs in JavaScript https://www.youtube.com/watch?v=Kw5tC5nQMRY&t=443s

2.4 Saving to a Database - Working with Data and APIs in JavaScript https://www.youtube.com/watch?v=xVYa20DCUv0

Read The Docs

Note

Nouveau: pour que Read The Docs puisse bien compiler il faut copier les trois fichiers .yaml, requirements.txt et conf.py depuis ce lien https://github.com/readthedocs/tutorial-template/tree/main

dans le répertoire windwaver (projet) on a le fichier readthedocs.yalm dont le contenu est le suivant:

dans le répertoire docs on a le fichier requirememts.txt dont le contenu est le suivant:

sphinx==7.1.2
sphinx-rtd-theme==1.3.0rc1

dans le répertoire source on a le fichier conf.py suivant: .. literalinclude:: /IT/sources/ReadTheDocs/conf.py

Ce tutoriel montre comment mettre en ligne un document fait avec ReStructureText en utilisant Read The Docs via Github.

Prérequis

  • Anaconda

  • un éditeur de texte (emacs)

  • un compte chez Github et l’installation sur PC (droits admin requis)

  • un compte chez Read The Docs (RTD)

Méthode

  1. créer un répertoire avec comme nom le nom du projet dans cet exemple c’est windwaver

  2. dans ce répertoire créer un répertoire nommé docs

  3. ouvrir Anaconda Prompt (pas le powershell)

  4. se déplacer dans le répertoire windwaver/docs

  5. tapez:

    sphinx-quickstart
    
  6. répondre à la question Seperate source … y Comme ça les fichiers make.bat et Makefile seront seront séparés du répertoire _sources dans lequel seront nos fichiers (.rst et le fichier config.py)

  7. ouvrir le fichier _sources/conf.py

  8. modifier la ligne html_theme = 'alabaster' par html_theme = 'sphinx_rtd_theme'

  9. ajouter la ligne suivante:master_doc = 'index' sinon ça bug avec Read The Docs

  10. cliquer-droite sur le répertoire windwaver et choisir Git Basch Here

  11. lancer la commande:

    git init
    
  12. lancer la commande:

    git config --global user.name 'Wind Waver'
    
  13. lancer la commande:

    git config --global user.email 'waverwind@gmail.com'
    
  14. lancer la commande:

    git add .
    
  15. lancer la commande:

    git status
    
  16. lancer la commande:

    git commit -m 'premier changement'
    

    premier changement est le commentaire de la modification

  17. sur https://github.com créer un nouveau répertoire et nommer le windwaver

  18. copier et coller la commande (dans le MINGW64):

    git remote add origin https://github.com/windwaver/windwaver.git
    
  19. copier et coller la commande:

    git push -u origin master
    
  20. créer le fichier README

    touch README.md
    
  21. décrire dans ce fichier le projet (à éditer dans emacs). Pour la mise en page c’est du Mark Down

  22. lancer la commande suivante:

    git add .
    
  23. lancer:

    git commit -m 'rajout de readme'
    
  24. ensuite:

    git push
    
  25. sur https://readthedocs.org cliquer sur importer et faire un refresh

  26. choisir le dossier windwaver

  27. cliquer sur build, cela va créer le site

  28. éditer les différents fichiers

  29. à chaque modification lancer les commandes suivante:

    git add .
    git commit -m 'commentaire de la modification'
    git push
    
  30. attendre quelques seconde et rafraichir le site avec F5

Permission denied

Il arrive parfois après la commande push -u... que le message suivant s’affiche:

../_images/Permissions-Denied.PNG
Méthode pour réparer
  1. touche windows tapez credential manager (pour l’anglais) ou gestionnaire d’identification (pour le français)

    ../_images/Credential-Manager.PNG
  2. repérer GitHub et cliquer sur remove

    ../_images/Credential-Manager-1.PNG

Divers liens

ericholscher

GitHub

  • La branche master est la branche de production. C’est-à-dire que c’est la branche qui a la version qui tourne sans bug.

  • La branche dev est la branche de dévellopement c’est là que les contributeurs apportent leur dévelopement. (preProd)

  • Les branches des contributeurs sont celles où les personnes développent leur programmes pour ensuite les merger sur la branche dev (ici la branche du contributeur c’est devYDU)

  • Les branches hotfix sont les branches qui permettent de directement fixer des problèmes urgents sur la branche master.

.gitignore

On indique dans ce fichier les éléments qui ne doivent pas être “pusher”. C’est souvent le résultat d’un programme comme par exemple ce qui a dans le répertoire build

On indiquera dans ce fichier, les éléments qui devront être ignorés comme suit:

build/html
build/latex

Ici on ne voudra pas que les répertoire html et latex soient “pusher””.

Déroulement

Merger et création des branches requises (mettre à jour son working repertory)

Voir d’abord les branches existantes:

  1. Se mettre dans le working directory à l’aide du terminal ;

  2. Faire un git pull

  • git log--graph (tapez q pour quitter)

  • ou taper git gui et aller dans Repository -> Visualize All Branch History

    • Si la branche dev et devYDU existent:

      1. On synchronise ce qui a sur le server dans sont répertoire de travail, taper: git pull (si pas déjà fait)

      2. Se déplacer dans la branche dev, taper: git checkout 'dev'

      3. On merge se qui a dans la branche master dans la branche dev: git merge 'master' (on se place dans répertoire cible et on précise le repertoire source à tirer vers soi, ici le répertoire source c’est master) Normalement la branche dev est à jour, mais si il existe des branches hotfix alors il faudra faire cette opération.

      4. Se déplacer dans la branche de devYDU, taper: git checkout 'devYDU'

      5. On merge se qui a dans la branche dev dans sa branche perso: git merge 'dev' (on se place dans répertoir cible et on précise le repertoire source à tirer vers soi, ici le répertoire source c’est dev)

    • Si les branches requises n’existent pas sur le serveur:

      1. On synchronise ce qui a sur le server dans son répertoire de travail, taper: git pull

      2. Créons notre branche perso en tapant: git branch 'devYDU' Ceci va créer une branche en local.

      3. Ensuite on la met sur le server: git push comme la branche n’existe pas encore git nous demande de lancer la commande suivante: git push --set-upstream origin devYDU

      4. Si besoin créer la branche dev: git branch 'dev' Ceci va créer une branche en local.

      5. Ensuite on la met sur le server: git push comme la branche n’existe pas encore git nous demande de lancer la commande suivante: git push --set-upstream origin dev

      6. Une fois les branches requises créées, on fait les points de la liste de ci-dessus (Si la branche dev et devYDU existent)

Faire ses modifications dans la branche devYDU

  1. Dès que les modifications ne présentent pas de bug, on va dire de prendre en compte les modifications à git, taper:

    1. git add .

    2. git commit -m 'dire ce que l'on a changer'

  2. On va poussez les changements de la branche devYDU au server: git push ;

Mise en preProd (merger nos changements dans la branche dev)

  1. faire un git pull au cas si la branche dev aurait subi des modifs

  2. Se déplacer dans la branche dev, taper: git checkout 'dev'

  3. git merge 'devYDU'

  4. On pousse la branche dev sur le serveur: git push

Mise en prod (merger la branche dev dans la branche master)

Une fois que la branche dev a été testée et n’a pas de bug, il est temps de la merger dans la branche master

  1. faire un git pull au cas si la branche dev aurait subi des modifs

  2. Se déplacer dans la branche master, taper: git checkout 'dev'

  3. git merge 'dev'

  4. On pousse la branche master sur le serveur: git push

Une bonne vidéo pour apprendre

Cliquer ici

Installation

Cliquer ici

Pour modifier un projet

  1. créer un repertoire

  2. clique-droite sur le répertoire et choisir git bash

  3. git init
    
  4. git config --global user.name 'Wind Waver'
    
  5. git config --global user.email 'waverwind@gmail.com'
    
  6. git clone https://github.com/windwaver/windwaver.git
    
  7. git pull
    
  8. git remote add origin https://github.com/windwaver/windwaver.git
    
  9. git push -u origin master
    

Petites applications

Cette section présente des petites applications ou outils permettant de faire des petites choses utiles.

GSview

Extraction d’une page d’un document pdf

  1. ouvrir avec GSview

  2. Fichier -> Convert

  3. choisir la bonne page et mettre Type à pdfwrite.

BRISS

Cette application permet de rogner une figure pdf.

Touches racourcis :

l

pour loader un fichier

c

pour rogner (crop)

GIMP

Convertir une image en .eps

  1. Fichier -> enregistrer sous

  2. entrer le nom_fichier.eps

Convertir divers formats

Convertir pdf en png

Essayer PDF to PNG ici

Convertir .rst en .tex

Essayer pandoc ici

Conversions du son

CD -> mp3
  • Avec Ubuntu 12.04, j’utilise asunder, c’est un bon programme car il extrait directement les métadonnées du CD.

  • soundKonverter : on peut aussi utiliser ce programme. Astuce : copier/coller le contenu du CD sur le disque dur.

Extraire une bande son

Pour couper (extraire/éditer) une bande son : Audacity

PLEX

Remote access

../_images/PlexRemoteAccess.png

Caméra de surveillance

Paramétrer l’alerte par email

  1. se connecter avec le cable réseau tjrs sur linux

  2. il faut changer l’ip de linux en tapant : sudo ifconfig eth0 192.168.0.1 netmask 255.255.255.0

    ../_images/Capture2.png

    on peut vérifier l’ip à tout moment en tapant ip a on peut aussi vérifier tous les ip qui sont connecté sur le réseau local en tapant nmap -sn 192.168.1.0/24

  3. ouvrir firefox et se connecter à l’adresse 192.168.0.20

  4. usr name : admin pwd: même que pour l’autre cam dl…

  5. pour pouvoir être alarmé par email on ouvrira l’assistant de détection (wizard) il n’y a que par le wizard où l’on peut activer l’alerte par email en tout cas pour 5222L. Entrer les données comme suit: Password est celui de hotmail

    ../_images/Capture3.png ../_images/Capture4.png ../_images/Capture11.png
  6. Ne pas oublier d’indiquer la plage de détection on peut aussi le faire après-coups avec le smartphone.