Iterare una classe Javascript per una serie di classi HTML

di il
1 risposte

Iterare una classe Javascript per una serie di classi HTML

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.

1 Risposte

  • Re: Iterare una classe Javascript per una serie di classi HTML

    BennyBatt ha scritto:


    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.
    Recuperi solo il primo tag <video> in quanto la funzione querySelector() restituisce solo il primo elemento che soddisfa la query specificata come parametro: vedi la documentazione che lo indica esplicitamente.

    Così a prima vista, direi che devi usare querySelectorAll() al suo posto (qui la documentazione).

    Ciao!
Devi accedere o registrarti per scrivere nel forum
1 risposte