thomas
This commit is contained in:
42
TP3/EX1/app.js
Normal file
42
TP3/EX1/app.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import { getMovies } from './model.js';
|
||||
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const searchBtn = document.getElementById('searchBtn');
|
||||
const movieList = document.getElementById('movie-list');
|
||||
|
||||
async function search(searchMovie) {
|
||||
if (searchMovie.trim() === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
const movies = await getMovies(searchMovie);
|
||||
renderMovies(movies);
|
||||
}
|
||||
|
||||
function renderMovies(movies) {
|
||||
movieList.innerHTML = '';
|
||||
if (movies.length === 0) {
|
||||
movieList.innerHTML = '<p>Aucun film trouvé.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
movies.forEach(movie => {
|
||||
const movieCard = document.createElement('div');
|
||||
movieCard.classList.add('movie-card');
|
||||
movieCard.innerHTML = `
|
||||
<h3>${movie.Title} (${movie.Year})</h3>
|
||||
<img src="${movie.Poster !== 'N/A' ? movie.Poster : 'https://via.placeholder.com/200x300.png?text=Pas+d%27image'}" alt="${movie.Title}">
|
||||
`;
|
||||
movieList.appendChild(movieCard);
|
||||
});
|
||||
}
|
||||
|
||||
searchBtn.addEventListener('click', () => {
|
||||
search(searchInput.value);
|
||||
});
|
||||
|
||||
searchInput.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
search(searchInput.value);
|
||||
}
|
||||
});
|
||||
24
TP3/EX1/index.html
Normal file
24
TP3/EX1/index.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Recherche de films</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; padding: 20px; }
|
||||
#search-container { margin-bottom: 20px; }
|
||||
#movie-list { display: flex; flex-wrap: wrap; gap: 20px; }
|
||||
.movie-card { width: 200px; border: 1px solid #ccc; padding: 10px; text-align: center; }
|
||||
.movie-card img { max-width: 100%; height: auto; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Recherche de films</h1>
|
||||
<div id="search-container">
|
||||
<input type="text" id="searchInput" placeholder="Titre du film...">
|
||||
<button id="searchBtn">Rechercher</button>
|
||||
</div>
|
||||
<div id="movie-list"></div>
|
||||
|
||||
<script type="module" src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
16
TP3/EX1/model.js
Normal file
16
TP3/EX1/model.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export async function getMovies(search) {
|
||||
const apiKey = '2fcb2848';
|
||||
const url = `https://www.omdbapi.com/?apikey=${apiKey}&s=${encodeURIComponent(search)}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
return data.Search || []; // Renvoie un tableau vide si aucun résultat
|
||||
} catch (error) {
|
||||
console.error("Erreur lors de la recherche de films:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
114
TP3/EX2/thrones.html
Normal file
114
TP3/EX2/thrones.html
Normal file
@@ -0,0 +1,114 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Personnages Game of Thrones</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
|
||||
<style>
|
||||
.character-card { text-align: center; }
|
||||
.character-card img { width: 128px; height: 128px; object-fit: cover; border-radius: 50%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-4">
|
||||
<h1 class="title has-text-centered">Personnages Game of Thrones</h1>
|
||||
<div class="field is-grouped is-grouped-centered">
|
||||
<p>Personnages par page:</p>
|
||||
<div class="control">
|
||||
<div class="select">
|
||||
<select id="pageSizeSelect">
|
||||
<option value="6">6</option>
|
||||
<option value="12">12</option>
|
||||
<option value="24">24</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="characters-container" class="columns is-multiline"></div>
|
||||
|
||||
<div class="buttons is-centered">
|
||||
<button id="prevBtn" class="button is-info">Précédent</button>
|
||||
<button id="nextBtn" class="button is-info">Suivant</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const charactersContainer = document.getElementById('characters-container');
|
||||
const pageSizeSelect = document.getElementById('pageSizeSelect');
|
||||
const prevBtn = document.getElementById('prevBtn');
|
||||
const nextBtn = document.getElementById('nextBtn');
|
||||
let allCharacters = [];
|
||||
let currentPage = 1;
|
||||
let pageSize = parseInt(pageSizeSelect.value);
|
||||
|
||||
const fetchCharacters = async () => {
|
||||
try {
|
||||
const response = await fetch('https://thronesapi.com/api/v2/Characters');
|
||||
allCharacters = await response.json();
|
||||
renderCharacters();
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la récupération des personnages:', error);
|
||||
charactersContainer.innerHTML = '<p class="has-text-danger has-text-centered">Erreur de chargement des données.</p>';
|
||||
}
|
||||
};
|
||||
|
||||
const renderCharacters = () => {
|
||||
charactersContainer.innerHTML = '';
|
||||
const startIndex = (currentPage - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const charactersToDisplay = allCharacters.slice(startIndex, endIndex);
|
||||
|
||||
charactersToDisplay.forEach(char => {
|
||||
const card = document.createElement('div');
|
||||
card.classList.add('column', 'is-one-quarter-desktop', 'is-one-third-tablet', 'is-half-mobile');
|
||||
card.innerHTML = `
|
||||
<div class="card character-card">
|
||||
<div class="card-image">
|
||||
<figure class="image is-128x128 is-inline-block mt-4">
|
||||
<img src="${char.imageUrl}" alt="${char.fullName}">
|
||||
</figure>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<p class="title is-4">${char.fullName}</p>
|
||||
<p class="subtitle is-6">${char.title}</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
charactersContainer.appendChild(card);
|
||||
});
|
||||
|
||||
updatePaginationButtons();
|
||||
};
|
||||
|
||||
const updatePaginationButtons = () => {
|
||||
prevBtn.disabled = currentPage === 1;
|
||||
nextBtn.disabled = currentPage * pageSize >= allCharacters.length;
|
||||
};
|
||||
|
||||
prevBtn.addEventListener('click', () => {
|
||||
if (currentPage > 1) {
|
||||
currentPage--;
|
||||
renderCharacters();
|
||||
}
|
||||
});
|
||||
|
||||
nextBtn.addEventListener('click', () => {
|
||||
if (currentPage * pageSize < allCharacters.length) {
|
||||
currentPage++;
|
||||
renderCharacters();
|
||||
}
|
||||
});
|
||||
|
||||
pageSizeSelect.addEventListener('change', () => {
|
||||
pageSize = parseInt(pageSizeSelect.value);
|
||||
currentPage = 1;
|
||||
renderCharacters();
|
||||
});
|
||||
|
||||
fetchCharacters();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
177
TP3/EX3/communes.html
Normal file
177
TP3/EX3/communes.html
Normal file
@@ -0,0 +1,177 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Communes de France</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
|
||||
<style>
|
||||
.container { max-width: 800px; }
|
||||
.is-loading::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border: 2px solid #ccc;
|
||||
border-top-color: #333;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s infinite linear;
|
||||
margin-left: 10px;
|
||||
}
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-4">
|
||||
<h1 class="title has-text-centered">Rechercher des communes</h1>
|
||||
<div class="field">
|
||||
<label class="label">Région</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select id="regionSelect"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Département</label>
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select id="departementSelect" disabled></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Rechercher une commune</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" id="searchInput" placeholder="Nom de la commune..." disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button id="sortBtn" class="button is-info" disabled>Trier</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="communesList" class="box mt-4"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const regionSelect = document.getElementById('regionSelect');
|
||||
const departementSelect = document.getElementById('departementSelect');
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const sortBtn = document.getElementById('sortBtn');
|
||||
const communesList = document.getElementById('communesList');
|
||||
let allCommunes = [];
|
||||
let sortOrder = 'asc';
|
||||
|
||||
const fetchRegions = async () => {
|
||||
const url = 'https://geo.api.gouv.fr/regions';
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const regions = await response.json();
|
||||
regionSelect.innerHTML = '<option value="">-- Sélectionnez une région --</option>';
|
||||
regions.forEach(region => {
|
||||
regionSelect.innerHTML += `<option value="${region.code}">${region.nom}</option>`;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erreur de chargement des régions:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchDepartements = async (regionCode) => {
|
||||
departementSelect.disabled = true;
|
||||
departementSelect.classList.add('is-loading');
|
||||
const url = `https://geo.api.gouv.fr/regions/${regionCode}/departements`;
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const departements = await response.json();
|
||||
departementSelect.innerHTML = '<option value="">-- Sélectionnez un département --</option>';
|
||||
departements.forEach(dep => {
|
||||
departementSelect.innerHTML += `<option value="${dep.code}">${dep.nom} (${dep.code})</option>`;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erreur de chargement des départements:', error);
|
||||
} finally {
|
||||
departementSelect.disabled = false;
|
||||
departementSelect.classList.remove('is-loading');
|
||||
}
|
||||
};
|
||||
|
||||
const fetchCommunes = async (departementCode) => {
|
||||
searchInput.disabled = true;
|
||||
sortBtn.disabled = true;
|
||||
communesList.innerHTML = '<p class="has-text-centered is-loading">Chargement des communes...</p>';
|
||||
const url = `https://geo.api.gouv.fr/departements/${departementCode}/communes`;
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
allCommunes = await response.json();
|
||||
renderCommunes(allCommunes);
|
||||
} catch (error) {
|
||||
console.error('Erreur de chargement des communes:', error);
|
||||
communesList.innerHTML = '<p class="has-text-danger has-text-centered">Erreur de chargement des communes.</p>';
|
||||
} finally {
|
||||
searchInput.disabled = false;
|
||||
sortBtn.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
const renderCommunes = (communes) => {
|
||||
communesList.innerHTML = '';
|
||||
if (communes.length === 0) {
|
||||
communesList.innerHTML = '<p class="has-text-centered">Aucune commune trouvée.</p>';
|
||||
return;
|
||||
}
|
||||
const ul = document.createElement('ul');
|
||||
communes.forEach(commune => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = `${commune.nom} (Code postal: ${commune.codesPostaux[0]})`;
|
||||
ul.appendChild(li);
|
||||
});
|
||||
communesList.appendChild(ul);
|
||||
};
|
||||
|
||||
regionSelect.addEventListener('change', (e) => {
|
||||
if (e.target.value) {
|
||||
fetchDepartements(e.target.value);
|
||||
} else {
|
||||
departementSelect.innerHTML = '<option value="">-- Sélectionnez un département --</option>';
|
||||
departementSelect.disabled = true;
|
||||
searchInput.disabled = true;
|
||||
sortBtn.disabled = true;
|
||||
communesList.innerHTML = '';
|
||||
}
|
||||
});
|
||||
|
||||
departementSelect.addEventListener('change', (e) => {
|
||||
if (e.target.value) {
|
||||
fetchCommunes(e.target.value);
|
||||
} else {
|
||||
searchInput.disabled = true;
|
||||
sortBtn.disabled = true;
|
||||
communesList.innerHTML = '';
|
||||
}
|
||||
});
|
||||
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const searchTerm = e.target.value.toLowerCase();
|
||||
const filteredCommunes = allCommunes.filter(c => c.nom.toLowerCase().includes(searchTerm));
|
||||
renderCommunes(filteredCommunes);
|
||||
});
|
||||
|
||||
sortBtn.addEventListener('click', () => {
|
||||
sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
|
||||
allCommunes.sort((a, b) => {
|
||||
const nameA = a.nom.toLowerCase();
|
||||
const nameB = b.nom.toLowerCase();
|
||||
if (nameA < nameB) return sortOrder === 'asc' ? -1 : 1;
|
||||
if (nameA > nameB) return sortOrder === 'asc' ? 1 : -1;
|
||||
return 0;
|
||||
});
|
||||
renderCommunes(allCommunes);
|
||||
});
|
||||
|
||||
fetchRegions();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
137
TP3/EX4/foxes.html
Normal file
137
TP3/EX4/foxes.html
Normal file
@@ -0,0 +1,137 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Jeu des renards</title>
|
||||
<style>
|
||||
body { font-family: sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background-color: #f0f0f0; }
|
||||
.grid-container {
|
||||
display: grid;
|
||||
border: 2px solid #333;
|
||||
background-color: #555;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
.cell {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: #777;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
color: white;
|
||||
}
|
||||
.cell:hover { background-color: #999; }
|
||||
.cell.shot { background-color: #333; cursor: not-allowed; }
|
||||
.cell.won { background-color: green; }
|
||||
#info-panel { margin-top: 20px; text-align: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Jeu des renards</h1>
|
||||
<div id="grid-container" class="grid-container"></div>
|
||||
<div id="info-panel">
|
||||
<p id="foxes-info">Renards restants : ?</p>
|
||||
<p id="tries-info">Coups joués : 0</p>
|
||||
<button id="reset-btn">Nouvelle partie</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const serverUrl = 'https://dwarves.iut-fbleau.fr/foxes/foxes.php';
|
||||
const gridContainer = document.getElementById('grid-container');
|
||||
const foxesInfo = document.getElementById('foxes-info');
|
||||
const triesInfo = document.getElementById('tries-info');
|
||||
const resetBtn = document.getElementById('reset-btn');
|
||||
|
||||
let gridSize = 10;
|
||||
let initialFoxes = 10;
|
||||
let currentFoxes = initialFoxes;
|
||||
let tries = 0;
|
||||
let gameOver = false;
|
||||
|
||||
const updateInfo = (foxes, newTries) => {
|
||||
currentFoxes = foxes;
|
||||
tries = newTries;
|
||||
foxesInfo.textContent = `Renards restants : ${currentFoxes}`;
|
||||
triesInfo.textContent = `Coups joués : ${tries}`;
|
||||
};
|
||||
|
||||
const resetGame = async () => {
|
||||
gameOver = false;
|
||||
gridContainer.innerHTML = '';
|
||||
const url = `${serverUrl}?new&size=${gridSize}&foxes=${initialFoxes}`;
|
||||
try {
|
||||
const response = await fetch(url, { credentials: 'omit' }); // 'omit' pour ignorer les cookies
|
||||
const data = await response.json();
|
||||
if (data.status === 'ok') {
|
||||
gridContainer.style.gridTemplateColumns = `repeat(${gridSize}, 1fr)`;
|
||||
for (let i = 0; i < gridSize * gridSize; i++) {
|
||||
const cell = document.createElement('div');
|
||||
cell.classList.add('cell');
|
||||
cell.dataset.x = i % gridSize;
|
||||
cell.dataset.y = Math.floor(i / gridSize);
|
||||
cell.addEventListener('click', handleShot);
|
||||
gridContainer.appendChild(cell);
|
||||
}
|
||||
updateInfo(data.foxes, data.tries);
|
||||
} else {
|
||||
alert('Erreur lors de la réinitialisation du jeu.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur:', error);
|
||||
alert('Erreur de connexion au serveur.');
|
||||
}
|
||||
};
|
||||
|
||||
const handleShot = async (event) => {
|
||||
if (gameOver || event.target.classList.contains('shot')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const x = event.target.dataset.x;
|
||||
const y = event.target.dataset.y;
|
||||
const url = `${serverUrl}?X=${x}&Y=${y}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, { credentials: 'omit' });
|
||||
const data = await response.json();
|
||||
|
||||
if (data.status === 'ok') {
|
||||
event.target.classList.add('shot');
|
||||
if (data.foxes === -1) {
|
||||
event.target.textContent = 'X';
|
||||
updateInfo(currentFoxes - 1, data.tries);
|
||||
} else {
|
||||
event.target.textContent = data.foxes;
|
||||
updateInfo(currentFoxes, data.tries);
|
||||
}
|
||||
} else if (data.status === 'win') {
|
||||
gameOver = true;
|
||||
updateInfo(0, data.tries);
|
||||
event.target.classList.add('won');
|
||||
event.target.textContent = 'X';
|
||||
setTimeout(() => alert(`Félicitations ! Vous avez gagné en ${data.tries} coups.`), 100);
|
||||
} else if (data.status === 'nok') {
|
||||
console.error('Erreur du serveur:', data.message);
|
||||
}
|
||||
|
||||
// Check for win condition client-side (if currentFoxes reaches 0)
|
||||
if (currentFoxes === 0 && !gameOver) {
|
||||
gameOver = true;
|
||||
setTimeout(() => alert(`Félicitations ! Vous avez gagné !`), 100);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Erreur:', error);
|
||||
}
|
||||
};
|
||||
|
||||
resetBtn.addEventListener('click', resetGame);
|
||||
resetGame();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user