TP01, TP02 & TP03EX01
This commit is contained in:
commit
2cfb5211c3
73
TP01/EX1/app.js
Normal file
73
TP01/EX1/app.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import render from "./modules/langton-renderer-canvas2d";
|
||||||
|
import Ant from "./modules/Ant.js";
|
||||||
|
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
antStateColors : ['red','yellow'],
|
||||||
|
tileStateColors : ['white','black'],
|
||||||
|
tileSize : 10
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// For the view
|
||||||
|
|
||||||
|
const STEP_INTERVAL = 5;
|
||||||
|
const BTN_AUTOPLAY_ID = 'autoplay';
|
||||||
|
const BTN_NEXT_MOVE_ID = 'next-move';
|
||||||
|
const BTN_RESET_ID = 'reset';
|
||||||
|
const MOVE_VAL_ID = 'move-value';
|
||||||
|
const BTN_PLUS_100_ID = 'plus-100';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let autoplayInterval;
|
||||||
|
let auto=false;
|
||||||
|
let canvas = document.querySelector("canvas");
|
||||||
|
|
||||||
|
|
||||||
|
canvas.width = window.innerWidth ;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
|
||||||
|
let ant = new Ant(Math.floor(canvas.width / options.tileSize),Math.floor(canvas.height/options.tileSize));
|
||||||
|
|
||||||
|
function boucle() {
|
||||||
|
ant.moveForward();
|
||||||
|
updateView(ant,canvas,options)
|
||||||
|
if (auto === true){
|
||||||
|
setTimeout(boucle, STEP_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById(BTN_AUTOPLAY_ID).addEventListener('click', () => {
|
||||||
|
auto = !auto;
|
||||||
|
boucle();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById(BTN_PLUS_100_ID).addEventListener('click', () => {
|
||||||
|
for (let i=0; i<100; i++){
|
||||||
|
ant.moveForward();
|
||||||
|
}
|
||||||
|
updateView(ant,canvas,options)
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById(BTN_NEXT_MOVE_ID).addEventListener('click', () => {
|
||||||
|
ant.moveForward();
|
||||||
|
updateView(ant,canvas,options)
|
||||||
|
})
|
||||||
|
|
||||||
|
document.getElementById(BTN_RESET_ID).addEventListener('click', () => {
|
||||||
|
ant.reset();
|
||||||
|
updateView(ant,canvas,options)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
function updateView(ant,canvas,options)
|
||||||
|
{
|
||||||
|
document.getElementById(MOVE_VAL_ID).textContent = `${ant.move}`;
|
||||||
|
render(ant,canvas,options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
updateView(ant,canvas,options,1)
|
47
TP01/EX1/index.html
Normal file
47
TP01/EX1/index.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="initial-scale=1,witdh=device-width">
|
||||||
|
|
||||||
|
<title>Fourmi de Langton</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
||||||
|
<style>
|
||||||
|
canvas {
|
||||||
|
position : absolute ;
|
||||||
|
top : 0;
|
||||||
|
left : 0;
|
||||||
|
z-index : -1;
|
||||||
|
}
|
||||||
|
.control {
|
||||||
|
position : absolute ;
|
||||||
|
top : 0;
|
||||||
|
left : 0;
|
||||||
|
width : auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="control m-6 has-text-centered">
|
||||||
|
<h4 class="has-text-primary-dark title is-4">
|
||||||
|
Fourmi de Langton
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<nav class="m-3">
|
||||||
|
<button class="button" id="next-move">Next</button>
|
||||||
|
<button class="button" id="autoplay">Auto</button>
|
||||||
|
<button class="button" id="plus-100">+100</button>
|
||||||
|
<button class="button" id="reset">reset</button>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<p class="mb-6 is-size-7">
|
||||||
|
Nombre de mouvements : <span id="move-value"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<canvas></canvas>
|
||||||
|
<script type="module" src="app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
86
TP01/EX1/modules/Ant.js
Normal file
86
TP01/EX1/modules/Ant.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
class Ant {
|
||||||
|
x = 0; // position
|
||||||
|
y = 0;
|
||||||
|
move = 0;
|
||||||
|
|
||||||
|
w = 0; // universe dimensions
|
||||||
|
h = 0;
|
||||||
|
|
||||||
|
direction = 0; // 0 90 180 270
|
||||||
|
state = 0;
|
||||||
|
tiles = null;
|
||||||
|
|
||||||
|
constructor (w,h)
|
||||||
|
{
|
||||||
|
this.tiles = new Array(w).fill(null);
|
||||||
|
this.tiles.forEach((el,i) => this.tiles[i] = new Array(h).fill(0));
|
||||||
|
this.w = w;
|
||||||
|
this.h = h;
|
||||||
|
this.x = Math.floor(w/2);
|
||||||
|
this.y = Math.floor(h/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.direction = 0;
|
||||||
|
this.x = Math.floor(this.w/2);
|
||||||
|
this.y = Math.floor(this.h/2);
|
||||||
|
this.state = 0;
|
||||||
|
this.tiles.forEach(el=>el.fill(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
moveForward()
|
||||||
|
{
|
||||||
|
switch (this.direction) {
|
||||||
|
case 0:
|
||||||
|
this.x = ((this.x + 1) + this.w) % this.w;
|
||||||
|
break
|
||||||
|
case 90:
|
||||||
|
this.y = ((this.y + 1) + this.h) % this.h;
|
||||||
|
break
|
||||||
|
case 180:
|
||||||
|
this.x = ((this.x - 1) + this.w) % this.w;
|
||||||
|
break
|
||||||
|
case 270:
|
||||||
|
this.y = ((this.y - 1) + this.h) % this.h;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
this.move ++;
|
||||||
|
this.computeNextState();
|
||||||
|
}
|
||||||
|
rotateRight() {
|
||||||
|
// TODO
|
||||||
|
this.direction = (this.direction+90)%360;
|
||||||
|
}
|
||||||
|
|
||||||
|
rotateLeft() {
|
||||||
|
// TODO
|
||||||
|
this.direction = (this.direction+270)%360;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeNextState()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
if (this.tiles[this.x][this.y]===1){ //noir
|
||||||
|
if (this.state ===1){
|
||||||
|
this.state = 0;
|
||||||
|
this.tiles[this.x][this.y] = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.rotateLeft();
|
||||||
|
this.tiles[this.x][this.y] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{ // blanc
|
||||||
|
if (this.state ===1){
|
||||||
|
this.rotateRight();
|
||||||
|
this.tiles[this.x][this.y] = 1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.state = 1;
|
||||||
|
this.tiles[this.x][this.y] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Ant;
|
99
TP01/EX1/modules/langton-renderer-canvas2d.js
Normal file
99
TP01/EX1/modules/langton-renderer-canvas2d.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* render - renders the universe to a 2D canvas.
|
||||||
|
*
|
||||||
|
* @param langtonsAnt - the universe.
|
||||||
|
* @param canvas - The 2D canvas.
|
||||||
|
* @param options - The rendering options (all optional).
|
||||||
|
* @returns {undefined} - Nothing is returned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function render(langtonsAnt, canvas, options) {
|
||||||
|
|
||||||
|
// Grab our options.
|
||||||
|
const {
|
||||||
|
tileStateColors,
|
||||||
|
antStateColors,
|
||||||
|
tileSize
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
|
||||||
|
// Drawing style.
|
||||||
|
const backgroundColor = '#FFFFFF';
|
||||||
|
|
||||||
|
// Size constants.
|
||||||
|
const w = canvas.width;
|
||||||
|
const h = canvas.height;
|
||||||
|
|
||||||
|
// Bounds constants.
|
||||||
|
const gridSizeW = langtonsAnt.tiles.length;
|
||||||
|
const gridSizeH = langtonsAnt.tiles[0].length;
|
||||||
|
|
||||||
|
// We're going to draw each square with a given edge size
|
||||||
|
|
||||||
|
const tileSizeW = tileSize//w / gridSizeW ;
|
||||||
|
const tileSizeH = tileSize //h / gridSizeH ;
|
||||||
|
|
||||||
|
// Get the drawing context.
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// Clear the background.
|
||||||
|
ctx.fillStyle = backgroundColor;
|
||||||
|
ctx.fillRect(0, 0, w, h);
|
||||||
|
|
||||||
|
// Draw the grid.
|
||||||
|
ctx.strokeStyle='#00000011';
|
||||||
|
for (let x = 0; x <= gridSizeW; x++) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x * tileSizeW , 0);
|
||||||
|
ctx.lineTo(x * tileSizeW , h);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
for (let y = 0 ; y <= gridSizeH; y++) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(0, y * tileSizeH);
|
||||||
|
ctx.lineTo(w, y * tileSizeH);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Start drawing those tiles.
|
||||||
|
langtonsAnt.tiles.forEach((tileRow,i) => {
|
||||||
|
tileRow.forEach((tile,j)=>{
|
||||||
|
|
||||||
|
// Get the tile state index.
|
||||||
|
|
||||||
|
// Skip state zero tiles (i.e. white tiles)
|
||||||
|
if (tile !== 0) {
|
||||||
|
// Set the tile colour, defaulting to grey if it is not set.
|
||||||
|
ctx.fillStyle = tileStateColors[tile] || '#CCCCCC';
|
||||||
|
ctx.fillRect(i * tileSizeW + 1, j * tileSizeH +1, tileSizeW - 1, tileSizeH - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// Draw the ant.
|
||||||
|
var antX = langtonsAnt.x * tileSizeW,
|
||||||
|
antY = langtonsAnt.y * tileSizeH;
|
||||||
|
const antState = langtonsAnt.state;
|
||||||
|
|
||||||
|
ctx.fillStyle = antStateColors[antState];
|
||||||
|
// Tranform before we draw the ant, it makes it easier.
|
||||||
|
//
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(antX + tileSizeW/2, antY+tileSizeH/2);
|
||||||
|
ctx.rotate((langtonsAnt.direction / 180) * Math.PI);
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(-tileSizeW/2, -tileSizeH/2);
|
||||||
|
ctx.lineTo(tileSizeW/2, 0);
|
||||||
|
ctx.lineTo(-tileSizeW/2, tileSizeH/2);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default render;
|
50
TP01/EX3/array.html
Normal file
50
TP01/EX3/array.html
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="initial-scale=1,witdh=device-width">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
||||||
|
|
||||||
|
<script src="graph.js" type="text/javascript"></script>
|
||||||
|
<script>
|
||||||
|
window.onload = (()=>{
|
||||||
|
let array = Array.from({length: 15}, () => -10 + Math.floor(Math.random() * 21));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
graph('graph1', array)
|
||||||
|
graph('graph2', array.map(function(nombre){return nombre+3}))
|
||||||
|
graph('graph3', array.slice().sort((a,b) => (a-b)))
|
||||||
|
graph('graph4', array.filter(function(nombre){return (nombre >= 0)}))
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="m-6">
|
||||||
|
<main class="container">
|
||||||
|
<section class="columns is-multiline">
|
||||||
|
|
||||||
|
<div class="column is-6">
|
||||||
|
<h2 class="title is-2">Simple Array</h2>
|
||||||
|
<canvas id="graph1" width="500" height="400"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column is-6">
|
||||||
|
<h2 class="title is-2">Add 3 (using map)</h2>
|
||||||
|
<canvas id="graph2" width="500" height="400"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column is-6">
|
||||||
|
<h2 class="title is-2">Sorted</h2>
|
||||||
|
<canvas id="graph3" width="500" height="400"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column is-6">
|
||||||
|
<h2 class="title is-2">Filtered (positives values)</h2>
|
||||||
|
<canvas id="graph4" width="500" height="400"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
34
TP01/EX3/graph.js
Normal file
34
TP01/EX3/graph.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const colors = [
|
||||||
|
'#00429d', '#204fa3', '#325da9', '#406aaf', '#4e78b5', '#5a86bb',
|
||||||
|
'#6694c1', '#73a2c6', '#80b1cc', '#8ebfd1', '#9dced6', '#addcda',
|
||||||
|
'#c0eade', '#d8f6e1', '#ffffe0'
|
||||||
|
]
|
||||||
|
|
||||||
|
function graph(canvasId, array) {
|
||||||
|
if (array.length == 0) {
|
||||||
|
throw "array.length == 0"
|
||||||
|
}
|
||||||
|
|
||||||
|
var min = array.reduce(function(a, b) { return (a < b)? a: b; })
|
||||||
|
var max = array.reduce(function(a, b) { return (a < b)? b: a; })
|
||||||
|
|
||||||
|
var canvas = document.getElementById(canvasId)
|
||||||
|
var context = canvas.getContext("2d")
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height)
|
||||||
|
|
||||||
|
context.beginPath()
|
||||||
|
context.strokeStyle = "black"
|
||||||
|
context.moveTo(0, canvas.height / 2)
|
||||||
|
context.lineTo(canvas.width, canvas.height / 2)
|
||||||
|
context.stroke()
|
||||||
|
|
||||||
|
array.forEach(function(v, i) {
|
||||||
|
|
||||||
|
context.fillStyle = colors[(i) % colors.length]
|
||||||
|
context.fillRect((i + 0.1) * canvas.width / array.length, canvas.height / 2, 0.8 * canvas.width / array.length, v * canvas.height / (min - max) / 2)
|
||||||
|
context.strokeText(v, (i + 0.4)* canvas.width / array.length, canvas.height /10)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
59
TP01/EX3/minmax.html
Normal file
59
TP01/EX3/minmax.html
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="http://www.iut-fbleau.fr/css/tacit.css">
|
||||||
|
</head>
|
||||||
|
<body class="m-6">
|
||||||
|
<main class="container">
|
||||||
|
<h2 class="title is-2">Random Array</h2>
|
||||||
|
<div id="line"></div>
|
||||||
|
|
||||||
|
<h2 class="title is-2">Min/Max</h2>
|
||||||
|
<p>
|
||||||
|
Min : <span id="min"></span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Max : <span id="max"></span>
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function getRandomArray(size,inf,max)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
let i;
|
||||||
|
let array = [];
|
||||||
|
for (i=0; i<size; i++){
|
||||||
|
let x = Math.floor(Math.random() * (max - inf + 1) + inf);
|
||||||
|
array[i] = x;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function minmax(array)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
if (array.length >= 0){
|
||||||
|
return array.reduce(function(resultat, nombre) {
|
||||||
|
return{
|
||||||
|
'min': Math.min(resultat.min, nombre),
|
||||||
|
'max': Math.max(resultat.max, nombre)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'min': Number.MAX_SAFE_INTEGER,
|
||||||
|
'max': Number.MIN_SAFE_INTEGER
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let array = getRandomArray(50,-100,100)
|
||||||
|
let minAndMax = minmax(array)
|
||||||
|
|
||||||
|
document.getElementById("line").textContent = array
|
||||||
|
document.getElementById('min').textContent = minAndMax.min
|
||||||
|
document.getElementById('max').textContent = minAndMax.max
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
22
TP02/EX01/data.js
Normal file
22
TP02/EX01/data.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
let data = [
|
||||||
|
{"idStanding":"2282066","intRank":"1","idTeam":"133714","strTeam":"Paris SG","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/rwqrrq1473504808.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"WLWWW","strDescription":"Promotion - Champions League (Group Stage)","intPlayed":"18","intWin":"15","intLoss":"1","intDraw":"2","intGoalsFor":"48","intGoalsAgainst":"13","intGoalDifference":"35","intPoints":"47","dateUpdated":"2023-01-12 23:01:12"},
|
||||||
|
{"idStanding":"2282067","intRank":"2","idTeam":"133822","strTeam":"Lens","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/3pxoum1598797195.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DWDWW","strDescription":"Promotion - Champions League (Group Stage)","intPlayed":"18","intWin":"12","intLoss":"1","intDraw":"5","intGoalsFor":"31","intGoalsAgainst":"13","intGoalDifference":"18","intPoints":"41","dateUpdated":"2023-01-12 23:01:12"},
|
||||||
|
{"idStanding":"2282068","intRank":"3","idTeam":"133707","strTeam":"Marseille","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/uutsyt1473504764.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"WWWWW","strDescription":"Promotion - Champions League (Qualification)","intPlayed":"18","intWin":"12","intLoss":"3","intDraw":"3","intGoalsFor":"36","intGoalsAgainst":"15","intGoalDifference":"21","intPoints":"39","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282069","intRank":"4","idTeam":"133719","strTeam":"Rennes","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/ypturx1473504818.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"LWLWD","strDescription":"Promotion - Europa League (Group Stage)","intPlayed":"18","intWin":"10","intLoss":"4","intDraw":"4","intGoalsFor":"35","intGoalsAgainst":"20","intGoalDifference":"15","intPoints":"34","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282070","intRank":"5","idTeam":"133823","strTeam":"Monaco","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/819x3z1655593495.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DWWLW","strDescription":"Promotion - Europa Conference League (Qualification)","intPlayed":"18","intWin":"10","intLoss":"4","intDraw":"4","intGoalsFor":"35","intGoalsAgainst":"25","intGoalDifference":"10","intPoints":"34","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282071","intRank":"6","idTeam":"133715","strTeam":"Lorient","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/sxsttw1473504748.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DWLDL","strDescription":"","intPlayed":"18","intWin":"9","intLoss":"4","intDraw":"5","intGoalsFor":"30","intGoalsAgainst":"26","intGoalDifference":"4","intPoints":"32","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282072","intRank":"7","idTeam":"133711","strTeam":"Lille","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/2giize1534005340.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DDWWD","strDescription":"","intPlayed":"18","intWin":"9","intLoss":"5","intDraw":"4","intGoalsFor":"30","intGoalsAgainst":"24","intGoalDifference":"6","intPoints":"31","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282073","intRank":"8","idTeam":"133713","strTeam":"Lyon","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/blk9771656932845.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DLWDL","strDescription":"","intPlayed":"18","intWin":"7","intLoss":"7","intDraw":"4","intGoalsFor":"27","intGoalsAgainst":"21","intGoalDifference":"6","intPoints":"25","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282074","intRank":"9","idTeam":"134713","strTeam":"Clermont Foot","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/wrytst1426871249.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"WWLLD","strDescription":"","intPlayed":"18","intWin":"7","intLoss":"7","intDraw":"4","intGoalsFor":"22","intGoalsAgainst":"26","intGoalDifference":"-4","intPoints":"25","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282075","intRank":"10","idTeam":"133712","strTeam":"Nice","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/msy7ly1621593859.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"WLDDW","strDescription":"","intPlayed":"18","intWin":"6","intLoss":"6","intDraw":"6","intGoalsFor":"22","intGoalsAgainst":"20","intGoalDifference":"2","intPoints":"24","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282076","intRank":"11","idTeam":"133934","strTeam":"Stade de Reims","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/xcrw1b1592925946.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"WDWDW","strDescription":"","intPlayed":"18","intWin":"5","intLoss":"4","intDraw":"9","intGoalsFor":"21","intGoalsAgainst":"23","intGoalDifference":"-2","intPoints":"24","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282077","intRank":"12","idTeam":"133703","strTeam":"Toulouse","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/3kqxs61547893229.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"WWLLL","strDescription":"","intPlayed":"18","intWin":"6","intLoss":"8","intDraw":"4","intGoalsFor":"28","intGoalsAgainst":"33","intGoalDifference":"-5","intPoints":"22","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282078","intRank":"13","idTeam":"134789","strTeam":"Troyes","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/swuwpq1426544753.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"LWDLD","strDescription":"","intPlayed":"18","intWin":"4","intLoss":"8","intDraw":"6","intGoalsFor":"29","intGoalsAgainst":"35","intGoalDifference":"-6","intPoints":"18","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282079","intRank":"14","idTeam":"133861","strTeam":"Nantes","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/8r0dab1598797469.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DWDDL","strDescription":"","intPlayed":"18","intWin":"3","intLoss":"6","intDraw":"9","intGoalsFor":"18","intGoalsAgainst":"24","intGoalDifference":"-6","intPoints":"18","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282080","intRank":"15","idTeam":"133709","strTeam":"Montpellier","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/spxtvu1473504783.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"LLWDD","strDescription":"","intPlayed":"18","intWin":"5","intLoss":"11","intDraw":"2","intGoalsFor":"28","intGoalsAgainst":"37","intGoalDifference":"-9","intPoints":"17","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282081","intRank":"16","idTeam":"133702","strTeam":"Ajaccio","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/qpxvwy1473505505.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"LLWDW","strDescription":"","intPlayed":"18","intWin":"4","intLoss":"11","intDraw":"3","intGoalsFor":"15","intGoalsAgainst":"27","intGoalDifference":"-12","intPoints":"15","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282082","intRank":"17","idTeam":"133704","strTeam":"Brest","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/z69be41598797026.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DLLWL","strDescription":"Relegation - Ligue 2","intPlayed":"18","intWin":"3","intLoss":"10","intDraw":"5","intGoalsFor":"18","intGoalsAgainst":"33","intGoalDifference":"-15","intPoints":"14","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282083","intRank":"18","idTeam":"134788","strTeam":"Auxerre","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/lzdtbf1658753355.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"LLLLD","strDescription":"Relegation - Ligue 2","intPlayed":"18","intWin":"3","intLoss":"11","intDraw":"4","intGoalsFor":"16","intGoalsAgainst":"40","intGoalDifference":"-24","intPoints":"13","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282084","intRank":"19","idTeam":"133882","strTeam":"Strasbourg","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/yuxtyy1464540071.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"DLLDL","strDescription":"Relegation - Ligue 2","intPlayed":"18","intWin":"1","intLoss":"8","intDraw":"9","intGoalsFor":"22","intGoalsAgainst":"33","intGoalDifference":"-11","intPoints":"12","dateUpdated":"2023-01-12 23:01:13"},
|
||||||
|
{"idStanding":"2282085","intRank":"20","idTeam":"134709","strTeam":"Angers","strTeamBadge":"https://www.thesportsdb.com/images/media/team/badge/445gc21622560255.png/tiny","idLeague":"4334","strLeague":"French Ligue 1","strSeason":"2022-2023","strForm":"LLLLL","strDescription":"Relegation - Ligue 2","intPlayed":"18","intWin":"2","intLoss":"14","intDraw":"2","intGoalsFor":"16","intGoalsAgainst":"39","intGoalDifference":"-23","intPoints":"8","dateUpdated":"2023-01-12 23:01:13"}
|
||||||
|
];
|
67
TP02/EX01/index.html
Normal file
67
TP02/EX01/index.html
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="initial-scale=1,witdh=device-width">
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" integrity="sha512-q3eWabyZPc1XTCmF+8/LuE1ozpg5xxn7iO89yfSOd5/oKvyqLngoNGsx8jq92Y8eXJ/IRxQbEC+FGSYxtk2oiw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
|
||||||
|
<!--link rel="stylesheet" href="./style.css"-->
|
||||||
|
|
||||||
|
<title>Classement Ligue 1</title>
|
||||||
|
</head>
|
||||||
|
<body class="m-6">
|
||||||
|
<main class="container">
|
||||||
|
<h3 class="title is-3 has-text-primary-dark">
|
||||||
|
Classement Ligue 1 de football<span class="tag" id="date"></span>
|
||||||
|
|
||||||
|
<div class="block control has-icons-left is-inline-block is-pulled-right">
|
||||||
|
<input class="input" type="search" placeholder="Equipe" id="myInput">
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-search"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<table class="table is-fullwidth is-hoverable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><abbr title="Position">Pos</abbr><a id="sort" onclick="trier()" href="#"><span class="icon"><i class="fas fa-sort"></i></span></a></th>
|
||||||
|
<th></th>
|
||||||
|
<th>Team</th>
|
||||||
|
<th><abbr title="Played">Pld</abbr></th>
|
||||||
|
<th><abbr title="Won">W</abbr></th>
|
||||||
|
<th><abbr title="Drawn">D</abbr></th>
|
||||||
|
<th><abbr title="Lost">L</abbr></th>
|
||||||
|
<th><abbr title="Goals for">GF</abbr></th>
|
||||||
|
<th><abbr title="Goals against">GA</abbr></th>
|
||||||
|
<th><abbr title="Goal difference">GD</abbr></th>
|
||||||
|
<th><abbr title="Points">Pts</abbr></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th><abbr title="Position">Pos</abbr></th>
|
||||||
|
<th></th>
|
||||||
|
<th>Team</th>
|
||||||
|
<th><abbr title="Played">Pld</abbr></th>
|
||||||
|
<th><abbr title="Won">W</abbr></th>
|
||||||
|
<th><abbr title="Drawn">D</abbr></th>
|
||||||
|
<th><abbr title="Lost">L</abbr></th>
|
||||||
|
<th><abbr title="Goals for">GF</abbr></th>
|
||||||
|
<th><abbr title="Goals against">GA</abbr></th>
|
||||||
|
<th><abbr title="Goal difference">GD</abbr></th>
|
||||||
|
<th><abbr title="Points">Pts</abbr></th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
<script src="data.js"></script>
|
||||||
|
<script src="script.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
71
TP02/EX01/script.js
Normal file
71
TP02/EX01/script.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
let table = document.getElementsByClassName("table")[0];
|
||||||
|
let trieCroissant = false;
|
||||||
|
let dat = ["intRank","strTeamBadge","strTeam","intPlayed","intWin","intDraw","intLoss","intGoalsFor","intGoalsAgainst","intGoalDifference","intPoints"];
|
||||||
|
let recherche = document.getElementById("myInput");
|
||||||
|
|
||||||
|
recherche.addEventListener('input', function(){
|
||||||
|
filtrer(recherche.value.toLowerCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
trier();
|
||||||
|
|
||||||
|
function viderTable(){
|
||||||
|
let listeLigne = table.children;
|
||||||
|
let i=0;
|
||||||
|
while (listeLigne.length>i){
|
||||||
|
if (listeLigne[i].tagName === 'tr'){
|
||||||
|
table.removeChild(listeLigne[i]);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function remplirTable(donnee=data){
|
||||||
|
for (let i=0; i<donnee.length; i++){
|
||||||
|
let ligne = createLine(donnee[i]);
|
||||||
|
table.appendChild(ligne);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function createLine(ligne){
|
||||||
|
let resultat = document.createElement("tr");
|
||||||
|
for(let i=0; i<dat.length; i++){
|
||||||
|
let colonne = document.createElement("th");
|
||||||
|
let contenu;
|
||||||
|
if (dat[i]==="strTeamBadge"){
|
||||||
|
contenu = document.createElement("img");
|
||||||
|
contenu.src = ligne[dat[i]];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
contenu = document.createTextNode(ligne[dat[i]]);
|
||||||
|
}
|
||||||
|
colonne.appendChild(contenu);
|
||||||
|
resultat.appendChild(colonne);
|
||||||
|
}
|
||||||
|
return resultat;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trier(){
|
||||||
|
trieCroissant = !trieCroissant;
|
||||||
|
if (trieCroissant === true){
|
||||||
|
data.sort((a,b)=>a.intRank - b.intRank);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
data.sort((a,b)=>b.intRank - a.intRank);
|
||||||
|
}
|
||||||
|
viderTable();
|
||||||
|
remplirTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
function filtrer(filtre){
|
||||||
|
viderTable();
|
||||||
|
let dataFiltrer = data.filter(function(equipe){
|
||||||
|
if (equipe.strTeam.toLowerCase().startsWith(filtre)){
|
||||||
|
return equipe;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
remplirTable(dataFiltrer);
|
||||||
|
}
|
32
TP02/EX02/css/style.css
Normal file
32
TP02/EX02/css/style.css
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
:focus-visible {outline:none;}
|
||||||
|
|
||||||
|
.strike {
|
||||||
|
text-decoration-line : line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loader.is-loading {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 999;
|
||||||
|
overflow: show;
|
||||||
|
margin: auto;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loader.is-loading:after {
|
||||||
|
animation: spinAround 500ms infinite linear;
|
||||||
|
border: 2px solid hsl(0deg, 0%, 86%);
|
||||||
|
border-radius: 9999px;
|
||||||
|
border-right-color: transparent;
|
||||||
|
border-top-color: transparent;
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
top: calc(50% - 5em);
|
||||||
|
left: calc(50% - 5em);
|
||||||
|
width: 10em;
|
||||||
|
height: 10em;
|
||||||
|
border-width: 0.25em;
|
||||||
|
}
|
48
TP02/EX02/index.html
Normal file
48
TP02/EX02/index.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<title>Todo</title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" integrity="sha512-q3eWabyZPc1XTCmF+8/LuE1ozpg5xxn7iO89yfSOd5/oKvyqLngoNGsx8jq92Y8eXJ/IRxQbEC+FGSYxtk2oiw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
<link rel="stylesheet" href="./css/style.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container content is-max-desktop p-4">
|
||||||
|
|
||||||
|
<div id="loader"></div>
|
||||||
|
<div class="has-text-centered">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- formulaire pour la saisie -->
|
||||||
|
|
||||||
|
<form id="add_form" class="block">
|
||||||
|
<p class="control has-icons-left is-expanded">
|
||||||
|
<input autocomplete="off" id="input_todo" class="input is-large is-expanded" type="text" placeholder="Enter Todo">
|
||||||
|
<span class="icon is-left">
|
||||||
|
<i class="fas fa-plus" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- filtrage de l'affichage -->
|
||||||
|
|
||||||
|
<div id="todos_filter" class="tabs is-small is-centered">
|
||||||
|
<ul>
|
||||||
|
<li class="is-active"><a href="#/" id="all">All</a></li>
|
||||||
|
<li><a href="#/active" id="active">Active</a></li>
|
||||||
|
<li><a href="#/done" id="done">Done</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!-- Affichage des todos -->
|
||||||
|
<section id="todos_list">
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
<script type="module" src="./js/app.js"></script>
|
||||||
|
|
||||||
|
</html>
|
6
TP02/EX02/js/app.js
Normal file
6
TP02/EX02/js/app.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import Controller from './controller.js'
|
||||||
|
import Model from './model.js'
|
||||||
|
import View from './view.js'
|
||||||
|
|
||||||
|
|
||||||
|
const app = new Controller(new Model(),new View())
|
54
TP02/EX02/js/controller.js
Normal file
54
TP02/EX02/js/controller.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
export default class Controller {
|
||||||
|
constructor(model, view) {
|
||||||
|
this.model = model
|
||||||
|
this.view = view
|
||||||
|
this.filter = "all"
|
||||||
|
this.view.bindAddTodo(this.addTodo.bind(this))
|
||||||
|
this.view.bindDeleteTodo(this.deleteTodo.bind(this))
|
||||||
|
this.view.bindToggleTodo(this.toggleTodo.bind(this))
|
||||||
|
this.view.bindEditTodo(this.editTodo.bind(this))
|
||||||
|
|
||||||
|
/** Routage **/
|
||||||
|
this.routes = ['all','active','done'];
|
||||||
|
|
||||||
|
/** Routage **/
|
||||||
|
window.addEventListener("load",this.routeChanged.bind(this));
|
||||||
|
window.addEventListener("hashchange",this.routeChanged.bind(this));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
routeChanged(){
|
||||||
|
let route = window.location.hash.replace(/^#\//,'');
|
||||||
|
this.filter = this.routes.find( r => r === route) || 'all';
|
||||||
|
this.filterTodoList();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
filterTodoList () {
|
||||||
|
let todos = this.model.getTodos(this.filter)
|
||||||
|
this.view.renderTodoList(todos)
|
||||||
|
this.view.setFilterTabs(this.filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
addTodo(text) {
|
||||||
|
let todo = this.model.add(text)
|
||||||
|
this.filterTodoList()
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTodo(id) {
|
||||||
|
this.model.delete(parseInt(id))
|
||||||
|
this.filterTodoList()
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleTodo(id) {
|
||||||
|
this.model.toggle(parseInt(id))
|
||||||
|
this.filterTodoList()
|
||||||
|
}
|
||||||
|
|
||||||
|
editTodo(id, text) {
|
||||||
|
this.model.edit(parseInt(id),text)
|
||||||
|
this.filterTodoList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
71
TP02/EX02/js/model.js
Normal file
71
TP02/EX02/js/model.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
const todos = [
|
||||||
|
{
|
||||||
|
id : 1,
|
||||||
|
text : "apprendre le javascript",
|
||||||
|
done : false
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id : 2,
|
||||||
|
text : "Faire des maths",
|
||||||
|
done : false
|
||||||
|
|
||||||
|
}]
|
||||||
|
|
||||||
|
export default class Model {
|
||||||
|
constructor() {
|
||||||
|
//this.todos = JSON.parse(localStorage.getItem('todos')) || []
|
||||||
|
this.todos = JSON.parse(localStorage.getItem('todos')) || todos
|
||||||
|
}
|
||||||
|
|
||||||
|
_commit(todos) {
|
||||||
|
localStorage.setItem('todos', JSON.stringify(todos))
|
||||||
|
}
|
||||||
|
|
||||||
|
getTodos(filter){
|
||||||
|
if (filter == "active")
|
||||||
|
return this.todos.filter(todo => !todo.done)
|
||||||
|
if (filter == "done")
|
||||||
|
return this.todos.filter(todo => todo.done)
|
||||||
|
|
||||||
|
return this.todos
|
||||||
|
}
|
||||||
|
|
||||||
|
add(todoText) {
|
||||||
|
const todo = {
|
||||||
|
id: this.todos.length > 0 ? this.todos[this.todos.length - 1].id + 1 : 1,
|
||||||
|
text: todoText,
|
||||||
|
done : false,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.todos.push(todo)
|
||||||
|
this._commit(this.todos)
|
||||||
|
return todo
|
||||||
|
}
|
||||||
|
|
||||||
|
edit(id, updatedText) {
|
||||||
|
let todo = this.todos.find(t => t.id === id)
|
||||||
|
todo.text = updatedText
|
||||||
|
// this.todos = this.todos.map(todo =>
|
||||||
|
// todo.id === id ? { id: todo.id, text: updatedText, done: todo.done} : todo
|
||||||
|
// )
|
||||||
|
|
||||||
|
this._commit(this.todos)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(id) {
|
||||||
|
this.todos = this.todos.filter(todo => todo.id !== id)
|
||||||
|
|
||||||
|
this._commit(this.todos)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle(id) {
|
||||||
|
let todo = this.todos.find(t => t.id === id)
|
||||||
|
todo.done = !todo.done
|
||||||
|
//this.todos = this.todos.map(todo =>
|
||||||
|
// todo.id === id ? { id: todo.id, text: todo.text, done: !todo.done } : todo
|
||||||
|
//)
|
||||||
|
this._commit(this.todos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
115
TP02/EX02/js/view.js
Normal file
115
TP02/EX02/js/view.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
export default class View {
|
||||||
|
constructor() {
|
||||||
|
this.form = document.querySelector("#add_form")
|
||||||
|
this.input = document.querySelector("#input_todo")
|
||||||
|
this.list = document.querySelector("#todos_list")
|
||||||
|
this.tabs = document.querySelector("#todos_filter")
|
||||||
|
this.loader = document.querySelector("#loader")
|
||||||
|
}
|
||||||
|
|
||||||
|
_getTodo() {
|
||||||
|
return this.input.value
|
||||||
|
}
|
||||||
|
|
||||||
|
_resetInput() {
|
||||||
|
this.input.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
_getNewTodoElement(todo){
|
||||||
|
let div = document.createElement("div")
|
||||||
|
div.classList.add("box","is-flex","is-align-items-center","m-2")
|
||||||
|
div.dataset.id = todo.id
|
||||||
|
|
||||||
|
let input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
input.classList.add("mr-3")
|
||||||
|
|
||||||
|
let span = document.createElement("p")
|
||||||
|
span.classList.add("mb-0","is-size-3","mr-auto")
|
||||||
|
span.textContent = todo.text
|
||||||
|
span.setAttribute("contenteditable",true)
|
||||||
|
|
||||||
|
|
||||||
|
let button = document.createElement("button")
|
||||||
|
button.classList.add("delete","is-large")
|
||||||
|
|
||||||
|
|
||||||
|
if (todo.done){
|
||||||
|
span.classList.add("strike")
|
||||||
|
input.checked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
div.append(input,span,button)
|
||||||
|
|
||||||
|
return div
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoader(){
|
||||||
|
this.loader.classList.add("is-loading")
|
||||||
|
}
|
||||||
|
unsetLoader(){
|
||||||
|
this.loader.classList.remove("is-loading")
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilterTabs(filter){
|
||||||
|
let li = this.tabs.querySelectorAll("li")
|
||||||
|
li.forEach( tab => {
|
||||||
|
tab.classList.remove("is-active")
|
||||||
|
})
|
||||||
|
let active = this.tabs.querySelector(`#${filter}`)
|
||||||
|
active.parentNode.classList.add("is-active")
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTodoList(todos) {
|
||||||
|
let list = new DocumentFragment()
|
||||||
|
for (let todo of todos){
|
||||||
|
list.appendChild(this._getNewTodoElement(todo))
|
||||||
|
}
|
||||||
|
this.list.replaceChildren(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Abonnements événements **/
|
||||||
|
|
||||||
|
bindAddTodo(handler) {
|
||||||
|
this.form.addEventListener("submit", (e=>{
|
||||||
|
e.preventDefault()
|
||||||
|
let text = this._getTodo()
|
||||||
|
handler(text)
|
||||||
|
this._resetInput()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bindDeleteTodo(handler) {
|
||||||
|
// TODO
|
||||||
|
this.list.addEventListener("click", (e) => {
|
||||||
|
let selection = e.target;
|
||||||
|
if (selection.tagName === "BUTTON"){
|
||||||
|
let id = selection.parentNode.dataset.id;
|
||||||
|
handler(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEditTodo(handler) {
|
||||||
|
this.list.addEventListener("keydown", (e) => {
|
||||||
|
let selection = e.target;
|
||||||
|
if (selection.tagName === "P" && e.key === "Enter"){
|
||||||
|
let id = selection.parentNode.dataset.id;
|
||||||
|
let texte = selection.textContent;
|
||||||
|
handler(id, texte);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bindToggleTodo(handler) {
|
||||||
|
this.list.addEventListener("change", (e) => {
|
||||||
|
let selection = e.target;
|
||||||
|
if (selection.tagName === "INPUT"){
|
||||||
|
let id = selection.parentNode.dataset.id;
|
||||||
|
handler(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
26
TP03/EX01/cookie.html
Normal file
26
TP03/EX01/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 id="cookie"src="img/cookie.png" alt="cookie">
|
||||||
|
<span id="score">0</span>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<button id="btnStart">start</button>
|
||||||
|
|
||||||
|
<p id="meme" class="hidden">
|
||||||
|
<img src="img/memee.png" alt="memee" width="64" height="64">
|
||||||
|
<span id="temps"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript" src="./js/game.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
TP03/EX01/css/img/bg.jpg
Normal file
BIN
TP03/EX01/css/img/bg.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
63
TP03/EX01/css/style.css
Normal file
63
TP03/EX01/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
TP03/EX01/img/bg.jpg
Normal file
BIN
TP03/EX01/img/bg.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
BIN
TP03/EX01/img/cookie.png
Normal file
BIN
TP03/EX01/img/cookie.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 103 KiB |
BIN
TP03/EX01/img/memee.png
Normal file
BIN
TP03/EX01/img/memee.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
48
TP03/EX01/js/game.js
Normal file
48
TP03/EX01/js/game.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
var btnStart = document.getElementById("btnStart");
|
||||||
|
var scoreView = document.getElementById("score");
|
||||||
|
var tempsView = document.getElementById("temps");
|
||||||
|
var meme = document.getElementById("meme");
|
||||||
|
var cookie = document.getElementById("cookie");
|
||||||
|
var score;
|
||||||
|
var temps;
|
||||||
|
var isPlayed=false;
|
||||||
|
var texte = " seconds left!";
|
||||||
|
var tailleCookieInitiale = cookie.naturalWidth;
|
||||||
|
|
||||||
|
btnStart.addEventListener('click', start);
|
||||||
|
cookie.addEventListener('click', clicCookie);
|
||||||
|
|
||||||
|
tempsView.style.color = "red";
|
||||||
|
|
||||||
|
function start(event){
|
||||||
|
if (!isPlayed){
|
||||||
|
meme.style.display="block";
|
||||||
|
cookie.style.width = tailleCookieInitiale+"px";
|
||||||
|
temps = 15;
|
||||||
|
score = 0;
|
||||||
|
scoreView.textContent = score;
|
||||||
|
isPlayed = true;
|
||||||
|
tempsView.textContent = temps+texte;
|
||||||
|
setTimeout(second,1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clicCookie(event){
|
||||||
|
if (isPlayed){
|
||||||
|
score ++;
|
||||||
|
cookie.style.width = (tailleCookieInitiale+score)+"px";
|
||||||
|
scoreView.textContent = score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function second(){
|
||||||
|
temps --;
|
||||||
|
tempsView.textContent = temps+texte;
|
||||||
|
if (temps <= 0){
|
||||||
|
isPlayed = false;
|
||||||
|
meme.style.display="none";
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setTimeout(second,1000);
|
||||||
|
}
|
||||||
|
}
|
11
TP03/EX02/css/style.css
Normal file
11
TP03/EX02/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
TP03/EX02/images/off.png
Normal file
BIN
TP03/EX02/images/off.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
BIN
TP03/EX02/images/on.png
Normal file
BIN
TP03/EX02/images/on.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
1
TP03/EX02/js/memory.js
Normal file
1
TP03/EX02/js/memory.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
// TODO
|
64
TP03/EX02/memory.html
Normal file
64
TP03/EX02/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,witdh=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>
|
Loading…
Reference in New Issue
Block a user