Buongorno a tutti.
Mi sono iscritto oggi, quindi saluto tutti quanti.
Non sono proprio un neofita, ma sto cercando di imparare JS, e mi rendo conto di avere lacune importanti.
Vengo al mio problmema. Sto cercando ci creare una classe JS con
constructor che mi permetta di abbinare controlli a diversi tag HTM VIDEO segnalati con l'omonima classe HTML 'video'.
La clsse JS funziona con un singolo VIDEO, ma mi sono impantanato cercando di legarla a più elementi nel codice HTLM. Credo ci siano dei difetti concettuali, non so.
Questo è il codice HTML:
<div class='player paused CVP'>
<video
class='video'
src='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'
width='700'
height='350'
poster='https://i.ytimg.com/vi/A1sVB8XBNDo/maxresdefault.jpg'
title="uno">
</video>
<div class='bigPlayBtn icon'></div>
<div class='playerController'>
<button class='player__btn miniPlayBtn icon' title='Play/Pause'></button>
<div class='timeCurr'>00:00</div>
<div class='progress'>
<span id='buffered'>
<div class='progressCurr'></div>
</span>
</div>
<div class='timeWhole'>--:--</div>
<div class='volumeContainer'>
<button class='player__btn max volumeBC icon'></button>
<input
type='range'
name='volume'
class='volume volumeRC'
min='0'
max='1'
step='0.01'
value='1'
title='Volume' />
</div>
<button class='player__btn fullscreen icon' title='Full Screen'></button>
</div>
</div>
<div class='player paused CVP'>
<video
class='video'
src='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4'
width='700'
height='350'
poster='https://i.ytimg.com/vi/A1sVB8XBNDo/maxresdefault.jpg'
title="due">
</video>
<div class='bigPlayBtn icon'></div>
<div class='playerController'>
<button class='player__btn miniPlayBtn icon' title='Play/Pause'></button>
<div class='timeCurr'>00:00</div>
<div class='progress'>
<span id='buffered'>
<div class='progressCurr'></div>
</span>
</div>
<div class='timeWhole'>--:--</div>
<div class='volumeContainer'>
<button class='player__btn max volumeBC icon'></button>
<input
type='range'
name='volume'
class='volume volumeRC'
min='0'
max='1'
step='0.01'
value='1'
title='Volume' />
</div>
<button class='player__btn fullscreen icon' title='Full Screen'></button>
</div>
</div>
Semplificando, si tratta di 2 sequenze con la classe 'player' contrassegnate per l'assegnamento alla classe JS con la classe 'CVP'. All'interno ci sono 2 tag VIDEO.
Il codice JS, imvece, è il seguente (è un po' lungo, ma è abbastanza leggibile):
class CVP {
constructor (obj) {
const { P, V, PC, BPB, MPB, VRC, VBC, FS, PROG, PROGC, TW, TC } = obj;
// player
this.player = P;
// video el
this.video = V;
// player controller
this.playerController = PC;
// play controlers
this.bigPlayBtn = BPB;
this.miniPlayBtn = MPB;
// volume controllers
this.volumeRangeController = VRC;
this.volumeBtnController = VBC;
// fullscreen
this.fullscreen = FS;
// progress bar
this.progress = PROG;
this.progressCurr = PROGC;
// time displayers
this.timeWhole = TW;
this.timeCurr = TC;
// bool vars
this.isMousedown = false;
this.isFullScreen = false;
// timer vars
this.timer = '';
this.timerTime = 1000;
}
setIsMouseDown = () => { this.isMousedown = !this.isMousedown;};
bigPlayBtnHandler = () => { this.bigPlayBtn.classList.toggle('HideBigPlayBtn');};
showHideControlls = () => { this.player.classList.toggle('paused');};
static changeIcon (target, remove, add) {
target.classList.remove(remove);
target.classList.add(add);
}
changePlayIcon () {
console.log(this.video.src);
target = player.miniPlayBtn;
let icon = this.video.paused ? 'play' : 'pause';
if (icon === 'pause') {
CVP.changeIcon(target, 'play', 'pause');
}else {
CVP.changeIcon(target, 'pause', 'play');
}
}
changeVolumeIcon (volElIconID) { // not in use
const target = document.querySelector(volElIconID);
if (this.video.muted) {
CVP.changeIcon(target, 'max', 'mute');
}else {
CVP.changeIcon(target, 'mute', 'max');
}
}
handleVideoTime (time) {
// minutes and seconds So Far
let hours;
let min = Math.floor(time / 60);
let sec = Math.floor(time % 60);
let output = '';
sec = (sec < 10) ? sec = `0${sec}` : sec;
min = (min < 10) ? min = `0${min}` : min;
output = `${min}:${sec}`;
return output;
}
rangeVolumeController () {
console.log(this);
this.video[this.name] = this.value;
if (player.volumeRangeController.value == 0) {
this.video.muted = true;
CVP.changeIcon(CVP.volumeBtnController, 'max', 'mute');
} else {
this.video.muted = false;
CVP.changeIcon(CVP.volumeBtnController, 'mute', 'max');
}
}
btnVolumeController () {
console.log(this);
if (this.video.muted) {
this.video.muted = false;
CVP.changeIcon(CVP.volumeBtnController, 'mute', 'max');
player.volumeRangeController.value = 1;
this.video.volume = 1;
} else {
this.video.muted = true;
CVP.changeIcon(CVP.volumeBtnController, 'max', 'mute');
player.volumeRangeController.value = 0;
}
}
hideWhenFullScreen () {
if (this.isFullScreen) {
this.playerController.hidden = false; // or this.playerController.style.bottom = '0px';
document.body.style.cursor = 'auto';
clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.playerController.hidden = true; // or this.playerController.style.bottom = '-50px';
document.body.style.cursor = 'none';
}, this.timerTime);
} else {
this.playerController.hidden = false; // or this.playerController.style.bottom = '0px';
document.body.style.cursor = 'auto';
}
}
toggleFullScreen () {
if (this.isFullScreen) {
if (document.exitFullscreen) { document.exitFullscreen();
}else if (document.mozCancelFullScreen) { document.mozCancelFullScreen();
}else if (document.webkitCancelFullScreen) { document.webkitCancelFullScreen();
}else if (document.msExitFullscreen) { document.msExitFullscreen();
}else { console.error('Unable to find a fullscreen exit method.');
}
} else {
if (this.player.requestFullscreen) { this.player.requestFullscreen();
} // standard
else if (this.player.webkitRequestFullscreen) { this.player.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
}else if (this.player.mozRequestFullScreen) { this.player.mozRequestFullScreen();
}else if (this.player.msRequestFullscreen) { this.player.msRequestFullscreen();
}else { console.error('Unable to find a fullscreen request method');}
}
}
toggleFullScreenHelper () {
this.player.classList.toggle('isFullScreen');
this.isFullScreen = !this.isFullScreen;
}
togglePlay() {
const action = this.video.paused ? 'play' : 'pause';
this.video[action]();
this.playerController.style.bottom = '0px';
this.changePlayIcon();
this.showHideControlls();
}
showVideoTime () {
console.log(cvp);
const { currentTime, duration } = this.video;
const pct = (currentTime / duration) * 100;
this.progressCurr.style.width = pct + '%';
this.timeCurr.innerText = this.handleVideoTime(currentTime.toFixed(0));
this.timeWhole.innerText = this.handleVideoTime(duration);
}
scrub (e) {
console.log(e);
console.log('e', e, 'this', this);
let seconds = (e.offsetX / this.progress.offsetWidth) * this.video.duration;
this.video.currentTime = seconds;
}
init () {
// Hook up the Event Listeners
// toggle Play
console.log(this.video);
this.video.addEventListener('click', this.togglePlay.bind(this));
this.miniPlayBtn.addEventListener('click', this.togglePlay.bind(this));
this.bigPlayBtn.addEventListener('click', this.togglePlay.bind(this));
// bigPlayBtn show/hide handler
this.video.addEventListener('click', this.bigPlayBtnHandler);
this.bigPlayBtn.addEventListener('click', this.bigPlayBtnHandler);
this.miniPlayBtn.addEventListener('click', this.bigPlayBtnHandler);
// time update
this.video.addEventListener('timeupdate', this.showVideoTime);
// progress bar events
this.progress.addEventListener('click', this.scrub.bind(this));
this.progress.addEventListener('mousemove', (e) => this.isMousedown && this.scrub(e));
this.progress.addEventListener('mousedown', this.setIsMouseDown);
this.progress.addEventListener('mouseup', this.setIsMouseDown);
// fullscreen
this.fullscreen.addEventListener('click', this.toggleFullScreen.bind(this));
// volume controllers
this.volumeBtnController.addEventListener('click', this.btnVolumeController);
this.volumeRangeController.addEventListener('change', this.rangeVolumeController);
this.volumeRangeController.addEventListener('mousemove', this.rangeVolumeController);
// cross-browser fullscreen hanlder
const browsersFullScreen = [
'fullscreenchange',
'mozfullscreenchange',
'webkitfullscreenchange',
'msfullscreenchange',
];
browsersFullScreen.forEach(browser => document.addEventListener(browser, this.toggleFullScreenHelper.bind(this)));
// player show/hide controlls on mousemove event
this.player.addEventListener('mousemove', this.hideWhenFullScreen.bind(this));
}
}
window.onload = function () {
const initializeCVP = {
P: document.querySelector('.CVP'),
V: document.querySelector('.video'),
PC: document.querySelector('.playerController'),
BPB: document.querySelector('.bigPlayBtn'),
MPB: document.querySelector('.miniPlayBtn'),
VRC: document.querySelector('.volumeRC'),
VBC: document.querySelector('.volumeBC'),
FS: document.querySelector('.fullscreen'),
PROG: document.querySelector('.progress'),
PROGC: document.querySelector('.progressCurr'),
TW: document.querySelector('.timeWhole'),
TC: document.querySelector('.timeCurr'),
};
const CVPs = document.querySelectorAll('.CVP');
CVPs.forEach((P) => {
initializeCVP.P = P;
cvp = new CVP(initializeCVP);
console.log(cvp.V);
cvp.init();
});
};
Tralascio i riferimenti al codice CSS per non appesantire ulteriormente la lettura.
Quello che accade è che nel metodo init() viene letto sempre e solo il primo tag VIDEO, nonostante l'iterazione del
forEach nella funzione
window.onload sia corretta.
Spero che qualcuno abbia la pazienza di analizzare il mio 'pasticcio'...
Grazie.