first commit with existing project files

This commit is contained in:
Vincent Guillet
2025-07-12 11:17:34 +02:00
commit 96bdccfe9f
8 changed files with 412 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
export class Playlist {
constructor() {
this._tracks = [];
}
get tracks() {
return this._tracks;
}
addTrack(track) {
this._tracks.push(track);
const div = document.createElement('div');
div.classList.add('d-flex');
div.classList.add('align-items-center');
div.classList.add('justify-content-between');
const deleteBtn = document.createElement('button');
deleteBtn.innerHTML = `<i class="bi bi-trash"></i>`;
deleteBtn.classList.add("btn");
deleteBtn.classList.add("btn-danger");
deleteBtn.classList.add("col-md-1");
deleteBtn.style.marginRight = "10px";
deleteBtn.addEventListener('click', (e) => {
e.preventDefault();
this._tracks.splice(this._tracks.indexOf(track), 1);
div.remove();
});
div.appendChild(deleteBtn);
const li = document.createElement('li');
li.classList.add("card");
li.classList.add("shadow-sm");
li.classList.add("p-4");
li.classList.add("col-md-11");
li.textContent = track.name;
li.style.margin = "5px 0";
div.appendChild(li);
div.setAttribute('id', this._tracks.indexOf(track).toString());
div.setAttribute('draggable', 'true');
div.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', e.target.id);
});
return div;
}
}

View File

@@ -0,0 +1,22 @@
export class Track {
constructor(name, url) {
this.name = name;
this.url = url;
}
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
get url() {
return this._url;
}
set url(value) {
this._url = value;
}
}

View File

@@ -0,0 +1,102 @@
import { Track } from './Track.js';
import { Playlist } from './Playlist.js';
const audio = document.getElementById('audioPlayer');
const playBtn = document.getElementById('playBtn');
const pauseBtn = document.getElementById('pauseBtn');
const resetBtn = document.getElementById('resetBtn');
const currentTimeSpan = document.getElementById('currentTime');
const totalTimeSpan = document.getElementById('totalTime');
const fileInput = document.getElementById('fileInput');
const loadFileBtn = document.getElementById('loadFileBtn');
const volume = document.getElementById('volume-slider');
const mediaInfo = document.querySelector('.media-info');
let timer = null;
let fileName;
let audioSrc;
let playlistElement = document.getElementById('playlist');
let playlist = new Playlist();
/* Functions */
function toReadableTime(seconds) {
return new Date(seconds * 1000).toISOString().substring(14, 19);
}
function updateTime() {
currentTimeSpan.textContent = toReadableTime(audio.currentTime);
}
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (file) {
audioSrc = URL.createObjectURL(file);
fileName = file.name.split('.mp3')[0];
}
});
/* Events */
loadFileBtn.addEventListener('click', () => {
const track = new Track(fileName, audioSrc);
playlistElement.appendChild(playlist.addTrack(track, playlistElement));
});
audio.addEventListener('loadedmetadata', () => {
totalTimeSpan.textContent = toReadableTime(audio.duration);
});
playBtn.addEventListener('click', () => {
audio.src = audioSrc;
audio.load();
mediaInfo.innerText = fileName;
updateTime();
audio.play();
if (!timer) {
timer = setInterval(updateTime, 500);
}
document.title = `Playing ${fileName}`;
});
pauseBtn.addEventListener('click', () => {
audio.pause();
});
if (audio.play()) {
resetBtn.addEventListener('click', () => {
audio.pause();
audio.currentTime = 0;
updateTime();
});
}
audio.addEventListener('ended', () => {
clearInterval(timer);
timer = null;
});
audio.addEventListener('pause', () => {
clearInterval(timer);
timer = null;
});
volume.addEventListener("input", function (e) {
audio.volume = e.currentTarget.value / 100;
});
volume.addEventListener("dblclick", function (e) {
audio.volume = 0.5;
e.currentTarget.value = 50;
});

View File

@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lecteur Audio HTML5</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<script type="module" src="app.js" defer></script>
</head>
<body class="bg-light py-5">
<div class="container">
<h1 class="mb-4 text-center">Lecteur Audio</h1>
<div class="card shadow-sm p-4">
<audio id="audioPlayer" src=""></audio>
<div class="d-flex justify-content-center align-items-center">
<h4 class="media-info">Aucun fichier chargé</h4>
</div>
<div class="d-flex justify-content-center gap-3 mb-3">
<button id="playBtn" class="btn btn-primary"><i class="bi bi-play-circle"></i></button>
<button id="pauseBtn" class="btn btn-warning"><i class="bi bi-pause-circle"></i></button>
<button id="resetBtn" class="btn btn-danger"><i class="bi bi-arrow-counterclockwise"></i></button>
</div>
<div class="d-flex justify-content-center align-items-center mb-3">
<input type="range" id="volume-slider">
</div>
<div class="text-center">
Temps écoulé : <span id="currentTime">00.00</span> / <span id="totalTime">00.00</span> sec
</div>
</div>
<hr>
<div class="card shadow-sm p-4">
<input type="file" id="fileInput" accept="audio/*" class="form-control mb-3">
<div class="d-flex justify-content-center">
<button id="loadFileBtn" class="btn btn-secondary">Ajouter à la playlist</button>
</div>
</div>
<hr>
<div class="card shadow-sm p-4">
<h4 class="mb-3">Playlist</h4>
<ul id="playlist">
</ul>
</div>
</div>
</body>
</html>