tp3
@ -4,6 +4,10 @@
|
||||
[Compléments de javascript](cours/jscomp.pdf) javascript, [tp1](./td_tp/tp1)
|
||||
|
||||
#### Semaine 2
|
||||
[DOM](cours/dom.pdf), [tp2](./td_tp/tp2)
|
||||
[DOM](cours/dom.pdf), [tp2](./td_tp/tp2), [tp2_bis](./td_tp/tp2_bis)
|
||||
|
||||
#### Semaine 3
|
||||
[Promesses, Ajax, API de données](cours/ajax.pdf), [tp3](./td_tp/tp3)
|
||||
|
||||
|
||||
|
||||
|
BIN
R4.01_R4.A.10/cours/ajax.pdf
Normal file
44
R4.01_R4.A.10/td_tp/tp2_bis/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
# TP javascript : DOM
|
||||
|
||||
Un peu [d'aide](./aide.md).
|
||||
|
||||
#### Ex1
|
||||
|
||||
Complétez le code du fichier <code>[game.js](./src/ex1/js/game.js)</code> inclus
|
||||
dans <code>[cookie.html](./src/ex1/cookie.html)</code> afin de concevoir un idle game
|
||||
consistant à cliquer sur un cookie le plus grand nombre de fois en 15
|
||||
secondes.
|
||||
|
||||
|
||||
<div style="text-align:center">
|
||||
<img src="./img/cookie1.png">
|
||||
<img src="./img/cookie2.png">
|
||||
</div>
|
||||
|
||||
#### Ex2 : memory
|
||||
|
||||
Le jeu tirera aléatoirement des ampoules allumées, les dévoilera
|
||||
pendant une seconde au joueur, puis les cachera à nouveau.
|
||||
Le joueur doit alors cliquer sur chaque ampoule initialement allumée. S'il se trompe,
|
||||
une alerte lui signifie qu'il a perdu. Lorsque toutes les ampoules ont été retrouvées, le joueur gagne.
|
||||
|
||||

|
||||
|
||||
Vous devez seulement complèter le fichier `memory.js`
|
||||
|
||||
|
||||
#### Ex3 **Glisser/Déposer** (pour ceux qui ont **tout** fait)
|
||||
Le but est de trier un tableau d'entiers, par ordre croissant, par glisser/déposer (drag and drop).
|
||||
|
||||
<img src="./img/tri.png" width="100%" class="img-polaroid">
|
||||
<img src="./img/tri1.png" width="100%" class="img-polaroid">
|
||||
<img src="./img/tri2.png" width="100%" class="img-polaroid">
|
||||
|
||||
Travail à faire
|
||||
- La génération des entiers dans les divisions "draggable".
|
||||
- La sensibilisation aux événements <code>dragstart, drop, dragover</code>. Vous trouverez toute l'information utilie sur l'interface drag and drog d'html5 <a target="_blank" href="http://www.w3schools.com/html/html5_draganddrop.asp">ici</a>.
|
||||
- Dans la zone correspondante au tableau trié, le fond change de couleur suivant que les entiers déjà déposés sont triés correctement ou non.
|
||||
|
||||
Pour gérer les classes css d'un noeud, vous pouvez utilisez la propriété <a href="https://developer.mozilla.org/fr/docs/Web/API/Element/classList" target="_blank">classList</a>.
|
||||
|
||||
|
118
R4.01_R4.A.10/td_tp/tp2_bis/aide.md
Normal file
@ -0,0 +1,118 @@
|
||||
#### Selection d'éléments
|
||||
|
||||
```js
|
||||
// le premier
|
||||
document.querySelector(".box")
|
||||
|
||||
// ou tous
|
||||
document.querySelectorAll(".box")
|
||||
|
||||
// avec l'id
|
||||
|
||||
document.getElementById("toto")
|
||||
|
||||
// selection d'un élément dans un autre
|
||||
|
||||
let container = document.querySeletor('.container')
|
||||
container.querySelector('.box')
|
||||
```
|
||||
|
||||
#### Traverser le dom
|
||||
|
||||
```js
|
||||
var box = document.querySelector(".box")
|
||||
box.nextElementSibling
|
||||
box.previousElementSibling
|
||||
box.parentElement
|
||||
box.childNodes
|
||||
```
|
||||
|
||||
#### Création/insertion d'éléments
|
||||
|
||||
```js
|
||||
let p = document.createElement('p')
|
||||
p.textContent="blabla"
|
||||
document
|
||||
.getElementById("myDiv")
|
||||
.appendChild(p)
|
||||
|
||||
div.replaceChildren(p)
|
||||
```
|
||||
|
||||
|
||||
#### Gestionnaire évènementiels
|
||||
|
||||
```js
|
||||
document.querySelector(".button").addEventListener("click", (e) => { /* ... */ })
|
||||
document.querySelector(".button").addEventListener("mouseenter", (e) => { /* ... */ })
|
||||
document.addEventListener("keyup", (e) => { /* ... */ })
|
||||
```
|
||||
|
||||
#### window/document prêt
|
||||
|
||||
```js
|
||||
|
||||
document.addEventListener("DOMContentLoaded",() = > { .....})
|
||||
// le dom a été construit (on n'attend pas le chargement du css, images, etc.
|
||||
|
||||
windon.addEventListener('load',()=>{...})
|
||||
// le dom est prêt et toutes les ressources ont été chargées.
|
||||
```
|
||||
|
||||
|
||||
#### Local storage
|
||||
|
||||
```js
|
||||
|
||||
localStorage.setItem('monChat', 'Tom')
|
||||
let cat = localStorage.getItem('myCat')
|
||||
localStorage.clear()
|
||||
```
|
||||
|
||||
#### Limiter les appels successifs à une fonction
|
||||
|
||||
```js
|
||||
function debounce(f,wait)
|
||||
{
|
||||
let timeout
|
||||
return function(...args){
|
||||
clearTimeout(timeout)
|
||||
timeout=setTimeout(()=>f(...args),wait)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Gestion du css depuis le DOM
|
||||
|
||||
```js
|
||||
// Select the first .box and change its text color to #000
|
||||
document.querySelector(".box").style.color = "#000";
|
||||
|
||||
// Set color to #000 and background to red
|
||||
var box = document.querySelector(".box")
|
||||
box.style.color = "#000"
|
||||
box.style.backgroundColor = "red"
|
||||
|
||||
// Set all styles at once (and override any existing styles)
|
||||
box.style.cssText = "color: #000; background-color: red"
|
||||
|
||||
|
||||
// Hide and show an element by changing "display" to block and none
|
||||
document.querySelector(".box").style.display = "none"
|
||||
document.querySelector(".box").style.display = "block"
|
||||
|
||||
// Add, remove, and the toggle the "focus" class
|
||||
var box = document.querySelector(".box")
|
||||
box.classList.add("focus")
|
||||
box.classList.remove("focus")
|
||||
box.classList.toggle("focus")
|
||||
|
||||
|
||||
box.classList.add("focus", "highlighted")
|
||||
box.classList.remove("focus", "highlighted")
|
||||
|
||||
box.classList.add("focus", "highlighted")
|
||||
box.classList.remove("focus", "highlighted")
|
||||
|
||||
```
|
||||
|
BIN
R4.01_R4.A.10/td_tp/tp2_bis/img/cookie1.png
Normal file
After ![]() (image error) Size: 256 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/img/cookie2.png
Normal file
After ![]() (image error) Size: 271 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/img/memory.png
Normal file
After ![]() (image error) Size: 62 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/img/tri.png
Normal file
After ![]() (image error) Size: 44 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/img/tri1.png
Normal file
After ![]() (image error) Size: 45 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/img/tri2.png
Normal file
After ![]() (image error) Size: 46 KiB |
26
R4.01_R4.A.10/td_tp/tp2_bis/src/ex1/cookie.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<title>Cookie clicker</title>
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Cookie clicker</h1>
|
||||
<figure>
|
||||
<img src="img/cookie.png" alt="cookie">
|
||||
<span>0</span>
|
||||
</figure>
|
||||
|
||||
<button>start</button>
|
||||
|
||||
<p class="hidden">
|
||||
<img src="img/memee.png" alt="memee" width="64" height="64">
|
||||
<span></span>
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript" src="./js/game.js"></script>
|
||||
</body>
|
||||
</html>
|
BIN
R4.01_R4.A.10/td_tp/tp2_bis/src/ex1/css/img/bg.jpg
Normal file
After ![]() (image error) Size: 54 KiB |
63
R4.01_R4.A.10/td_tp/tp2_bis/src/ex1/css/style.css
Normal file
@ -0,0 +1,63 @@
|
||||
@import url(https://fonts.googleapis.com/css?family=Kavoon);
|
||||
|
||||
body {
|
||||
background-image: url("img/bg.jpg");
|
||||
background-repeat: repeat;
|
||||
font-family: Kavoon;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 320px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 28px;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
padding: 10px 40px 10px 40px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
figure {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
figure > span {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
right: 50px;
|
||||
border-radius: 21px;
|
||||
height: 42px;
|
||||
width: 56px;
|
||||
background-color: #f4d03f;
|
||||
box-shadow: 4px 4px 4px black;
|
||||
padding-top: 9px;
|
||||
}
|
||||
|
||||
button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-family: Kavoon;
|
||||
font-size: 24px;
|
||||
background-color: white;
|
||||
padding: 9px;
|
||||
border-radius: 10px;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
img[alt="GrandMa"] {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
BIN
R4.01_R4.A.10/td_tp/tp2_bis/src/ex1/img/bg.jpg
Normal file
After ![]() (image error) Size: 54 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/src/ex1/img/cookie.png
Normal file
After ![]() (image error) Size: 103 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/src/ex1/img/memee.png
Normal file
After ![]() (image error) Size: 11 KiB |
1
R4.01_R4.A.10/td_tp/tp2_bis/src/ex1/js/game.js
Normal file
@ -0,0 +1 @@
|
||||
// TODO
|
11
R4.01_R4.A.10/td_tp/tp2_bis/src/ex2/css/style.css
Normal file
@ -0,0 +1,11 @@
|
||||
img{
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
#gagne,#perdu,.hidden{
|
||||
display : none;
|
||||
}
|
||||
|
||||
.progress::-webkit-progress-value {
|
||||
transition: width 0.5s ease;
|
||||
}
|
BIN
R4.01_R4.A.10/td_tp/tp2_bis/src/ex2/images/off.png
Normal file
After ![]() (image error) Size: 9.1 KiB |
BIN
R4.01_R4.A.10/td_tp/tp2_bis/src/ex2/images/on.png
Normal file
After ![]() (image error) Size: 9.5 KiB |
1
R4.01_R4.A.10/td_tp/tp2_bis/src/ex2/js/memory.js
Normal file
@ -0,0 +1 @@
|
||||
// TODO
|
64
R4.01_R4.A.10/td_tp/tp2_bis/src/ex2/memory.html
Normal file
@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="initial-scale=1,width=device-width">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
<script src="./js/memory.js"></script>
|
||||
|
||||
<title>Memory</title>
|
||||
</head>
|
||||
|
||||
<body class="m-4">
|
||||
<main class="container">
|
||||
<h1 class="title is-1 has-text-primary">Memory</h1>
|
||||
<div class="columns">
|
||||
<div class="column is-6">
|
||||
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<img src="./images/off.png" alt="" />
|
||||
<img src="./images/off.png" alt="" />
|
||||
<img src="./images/off.png" alt="" />
|
||||
</div>
|
||||
<div class="column">
|
||||
<img src="./images/off.png" alt="" />
|
||||
<img src="./images/off.png" alt="" />
|
||||
<img src="./images/off.png" alt="" />
|
||||
</div>
|
||||
<div class="column">
|
||||
<img src="./images/off.png" alt="" />
|
||||
<img src="./images/off.png" alt="" />
|
||||
<img src="./images/off.png" alt="" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-6">
|
||||
<h3 class="title is-3 has-text-primary">Règles</h3>
|
||||
<p class="block is-size-4">
|
||||
Pendant une seconde, vous verrez l'état de l'ensemble
|
||||
des ampoules, puis elles seront éteintes. Vous devrez
|
||||
alors cliquer sur celles qui étaient allumées.
|
||||
</p>
|
||||
|
||||
<button class="block button is-info">COMMENCER</button>
|
||||
<progress id="temps" class="progress is-primary" value="100" max="100"></progress>
|
||||
|
||||
<!--div id="temps">10</div-->
|
||||
|
||||
<div class="notification is-danger is-size-4 p-4" id="perdu">
|
||||
<p>Perdu ! </p>
|
||||
</div>
|
||||
<div class="notification is-success is-size-4 p-4" id="gagne">
|
||||
<p>Gagné ! </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
46
R4.01_R4.A.10/td_tp/tp2_bis/src/ex3/css/style.css
Normal file
@ -0,0 +1,46 @@
|
||||
.slot{
|
||||
width:52px;
|
||||
height:52px;
|
||||
padding:2px;
|
||||
margin:11px;
|
||||
border:1px solid #aaaaaa;
|
||||
background-color:#ffffff;
|
||||
display:inline-block;
|
||||
vertical-align:middle;
|
||||
}
|
||||
.drag{
|
||||
width:50px;
|
||||
height:50px;
|
||||
border:1px solid #aaaaaa;
|
||||
background-color:#eeeeee;
|
||||
text-align:center;
|
||||
font-size:25px;
|
||||
line-height:52px;
|
||||
}
|
||||
|
||||
.ct{
|
||||
height:100px;
|
||||
margin:10px;
|
||||
line-height:100px;
|
||||
text-align:center;
|
||||
|
||||
}
|
||||
.normal{
|
||||
|
||||
background-color:#1583CC;
|
||||
|
||||
}
|
||||
|
||||
.good{
|
||||
background-color:#00867F;
|
||||
|
||||
}
|
||||
.wrong{
|
||||
|
||||
background-color:#eeaaaa;
|
||||
}
|
||||
|
||||
[draggable=true] {
|
||||
cursor: move;
|
||||
}
|
||||
|
3
R4.01_R4.A.10/td_tp/tp2_bis/src/ex3/js/tri.js
Normal file
@ -0,0 +1,3 @@
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min)) + min
|
||||
}
|
63
R4.01_R4.A.10/td_tp/tp2_bis/src/ex3/tri.html
Normal file
@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<script src="./js/tri.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h3>Drag and Drop</h3>
|
||||
|
||||
<!-- Le tableau initial -->
|
||||
|
||||
<div class="ct normal" id="start">
|
||||
<div class="slot">
|
||||
<div id="drag1" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag2" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag3" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag4" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag5" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag6" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag7" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag8" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag9" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
<div class="slot">
|
||||
<div id="drag10" class="drag" draggable="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Le tableau doit être trié ici -->
|
||||
|
||||
<div class="ct good" id="end">
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
<div class="slot"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
36
R4.01_R4.A.10/td_tp/tp3/README.md
Normal file
@ -0,0 +1,36 @@
|
||||
# TP javascript : Ajax, promesses.
|
||||
|
||||
Vous disposez tous, à la racine de votre compte, d'un répertoire `public_html` qui est servi (http/https) par le serveur dwarves.
|
||||
Pour accéder à vos pages, utilisez l'url :
|
||||
|
||||
> http(s)://dwarves.[arda|iut-fbleau.fr]/~login
|
||||
|
||||
Pour tester les différentes api http, vous pouvez utilisez la commande `curl`.
|
||||
|
||||
|
||||
#### Ex1
|
||||
Le but est de faire une recherche de film en utilisant l'api [OMDb](https://www.omdbapi.com/) (Open Movie Database).
|
||||
|
||||

|
||||
|
||||
Son utilisation nécessite une clé. Vous pouvez utiliser la mienne `2fcb2848`. Si
|
||||
la limite de requêtes est atteinte, générez votre propre clé.
|
||||
|
||||
|
||||
Complétez le [code](./src/ex1).
|
||||
- J'ai volontairement utilisé des modules. Il vous faut donc tester l'application avec
|
||||
http.
|
||||
- Écrire la fonction du modèle
|
||||
```js
|
||||
getMovies(search)
|
||||
```
|
||||
Cette fonction renvoie une promesse qui permet de faire une requête ajax vers l'api OMDb. Pour ajax,
|
||||
utilisez d'abord l'interface `fetch`, puis l'objet `XMLHttpRequest`.
|
||||
|
||||
- Ecrire la fonction du contrôleur
|
||||
```js
|
||||
async search(searchMovie)
|
||||
```
|
||||
qui permet de faire une recherche. Cette fonction utilise évidemment la fonction précédente `getMovies`.
|
||||
|
||||
|
35
R4.01_R4.A.10/td_tp/tp3/aide.md
Normal file
@ -0,0 +1,35 @@
|
||||
#### XMLHttpRequest
|
||||
```js
|
||||
let xhr = new XMLHttpRequest()
|
||||
xhr.open("GET","mon/url")
|
||||
|
||||
xhr.onload = ...
|
||||
xhr.onerror = ...
|
||||
|
||||
xhr.send()
|
||||
```
|
||||
#### Promise
|
||||
```js
|
||||
|
||||
let promise = new Promise ((resolve,reject) => {
|
||||
setTimeout(() => {
|
||||
resolve("OK")
|
||||
},1000)
|
||||
})
|
||||
promise.then(data => ....)
|
||||
```
|
||||
|
||||
#### async/await
|
||||
|
||||
```js
|
||||
|
||||
function getUser(email){
|
||||
return new Promise(...)
|
||||
}
|
||||
|
||||
async function updateUser(){
|
||||
|
||||
let user = await getUser(...)
|
||||
console.log(user)
|
||||
}
|
||||
```
|
BIN
R4.01_R4.A.10/td_tp/tp3/img/foot.png
Normal file
After ![]() (image error) Size: 125 KiB |
BIN
R4.01_R4.A.10/td_tp/tp3/img/got.png
Normal file
After ![]() (image error) Size: 984 KiB |
BIN
R4.01_R4.A.10/td_tp/tp3/img/search.png
Normal file
After ![]() (image error) Size: 320 KiB |
87
R4.01_R4.A.10/td_tp/tp3/src/ex1/css/style.css
Normal file
@ -0,0 +1,87 @@
|
||||
main {
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
.loader {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.loader {
|
||||
margin: 6rem 0 0;
|
||||
}
|
||||
.error {
|
||||
color: #FFFAAA;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
label {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
label span {
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
|
||||
}
|
||||
input {
|
||||
margin: 1rem 0 0;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 300;
|
||||
padding: 0.8rem 1rem;
|
||||
color: white;
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
transition: all 0.3s;
|
||||
box-shadow: 1px 1px 2px rgba(0,0,0, 0.3);
|
||||
-moz-appearance:none;
|
||||
-webkit-appearance:none;
|
||||
outline: none;
|
||||
}
|
||||
input:focus {
|
||||
border: 1px solid transparent;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 1rem 0 2rem;
|
||||
}
|
||||
ul li {
|
||||
padding: 0.6rem 1rem;
|
||||
margin: 1px 0;
|
||||
line-height: 1.4rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-content: space-between;
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 0 2px rgba(0,0,0, 0.3);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
ul li:hover,
|
||||
ul li:active,
|
||||
ul li:focus {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
ul li a {
|
||||
margin: 0 0.6rem 0 0;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
ul li span {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial;
|
||||
font-weight: 300;
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
background-image: -webkit-radial-gradient(ellipse farthest-corner at top, #661141, #000000);
|
||||
background-image: radial-gradient(ellipse farthest-corner at top, #661141, #000000);
|
||||
color: white;
|
||||
}
|
13
R4.01_R4.A.10/td_tp/tp3/src/ex1/img/puff.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<svg width="44" height="44" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="#fff">
|
||||
<g fill="none" fill-rule="evenodd" stroke-width="2">
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r" begin="0s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/>
|
||||
<animate attributeName="stroke-opacity" begin="0s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r" begin="-0.9s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/>
|
||||
<animate attributeName="stroke-opacity" begin="-0.9s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
After (image error) Size: 1.0 KiB |
28
R4.01_R4.A.10/td_tp/tp3/src/ex1/index.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="initial-scale=1,width=device-width">
|
||||
<link rel="stylesheet" type="text/css" href="./css/style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- vue html -->
|
||||
<main>
|
||||
<label>
|
||||
<span>Search a movie</span>
|
||||
<input type="input" placeholder="28 Days Later..">
|
||||
</label>
|
||||
|
||||
<div class="loader">
|
||||
<img src="./img/puff.svg">
|
||||
</div>
|
||||
|
||||
<p class="error"></p>
|
||||
<div id="list-movies">
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
<script type="module" src="./js/app.js"></script>
|
||||
</html>
|
7
R4.01_R4.A.10/td_tp/tp3/src/ex1/js/app.js
Normal file
@ -0,0 +1,7 @@
|
||||
import model from './model.js'
|
||||
import Controller from './controller.js'
|
||||
import View from './view.js'
|
||||
|
||||
const view = new View()
|
||||
const app = new Controller(view,model)
|
||||
|
26
R4.01_R4.A.10/td_tp/tp3/src/ex1/js/controller.js
Normal file
@ -0,0 +1,26 @@
|
||||
class Controller {
|
||||
constructor(view,model){
|
||||
this.view = view
|
||||
this.model = model
|
||||
|
||||
this.loading = false
|
||||
this.lastSearch = null
|
||||
this.error = null
|
||||
this.results = []
|
||||
|
||||
this.view.setLoading(false)
|
||||
this.view.bindSearch(this.search.bind(this))
|
||||
}
|
||||
reset() {
|
||||
this.loading = false
|
||||
this.error = null
|
||||
this.results = []
|
||||
}
|
||||
|
||||
async search(searchMovie) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
export default Controller
|
||||
|
12
R4.01_R4.A.10/td_tp/tp3/src/ex1/js/helpers.js
Normal file
@ -0,0 +1,12 @@
|
||||
// Returns a function, that, as long as it continues to be invoked, will not
|
||||
// be triggered. The function will be called after it stops being called for
|
||||
// N milliseconds.
|
||||
function debounce(fn, wait) {
|
||||
let timeout
|
||||
|
||||
return (...args) => {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => fn(...args), wait)
|
||||
}
|
||||
}
|
||||
export default debounce
|
9
R4.01_R4.A.10/td_tp/tp3/src/ex1/js/model.js
Normal file
@ -0,0 +1,9 @@
|
||||
let apiKey = '2fcb2848'
|
||||
|
||||
let model = {
|
||||
getMovies(search){
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
export default model
|
54
R4.01_R4.A.10/td_tp/tp3/src/ex1/js/view.js
Normal file
@ -0,0 +1,54 @@
|
||||
import debounce from "./helpers.js"
|
||||
|
||||
class View {
|
||||
constructor(){
|
||||
this.listMovies = document.querySelector("#list-movies")
|
||||
this.inputSearch = document.querySelector("input")
|
||||
this.loader = document.querySelector(".loader")
|
||||
this.message = document.querySelector("p.error")
|
||||
}
|
||||
|
||||
_getInput(){
|
||||
return this.inputSearch.value
|
||||
}
|
||||
|
||||
setLoading(loading){
|
||||
if (loading)
|
||||
this.loader.style.display = "block"
|
||||
else
|
||||
this.loader.style.display = "none"
|
||||
}
|
||||
|
||||
renderMessage(error){
|
||||
this.message.style.display = "block"
|
||||
this.message.textContent = error
|
||||
}
|
||||
|
||||
renderList(movies){
|
||||
let ul = document.createElement("ul")
|
||||
movies.forEach((movie)=>{
|
||||
let li = document.createElement("li")
|
||||
let a = document.createElement("a")
|
||||
let span = document.createElement("span")
|
||||
a.href = `http://www.imdb.com/title/${movie.imdbID}`
|
||||
a.target="_blank"
|
||||
a.textContent = movie.Title
|
||||
span.textContent = movie.Year
|
||||
|
||||
|
||||
li.appendChild(a)
|
||||
li.appendChild(span)
|
||||
ul.appendChild(li)
|
||||
})
|
||||
|
||||
this.listMovies.replaceChildren(ul)
|
||||
}
|
||||
|
||||
bindSearch(handler){
|
||||
this.inputSearch.addEventListener("input",debounce((e)=>{
|
||||
handler(this._getInput())
|
||||
},500))
|
||||
}
|
||||
}
|
||||
|
||||
export default View
|