• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Odtwarzacz muzyki na stronie

Object Storage Arubacloud
+1 głos
431 wizyt
pytanie zadane 10 lutego 2022 w JavaScript przez CanoNee Nowicjusz (230 p.)

Dzień Dobry,

Tworzę odtwarzacz muzyki na stronę, który będzie domyślnie zawierał 14 playlist, jednak w trakcie pisania strony natknąłem się na jeden problem - wybrana playlista jest uruchamiana wyłącznie przez nieparzyste kliknięcia na stronie, każde parzyste kliknięcie powoduje problemy.

Łopatologicznie: 

  1. Klikam na playlistę A pojedynczym kliknięciem - działa bez zarzutu
  2. Następnie wybieram pojedynczym kliknięciem playlistę B - nie działa
  3. Wracam pojedynczym kliknięciem na playlistę A - działa bez zarzutu
  4. Następnie wybieram podwójnym kliknięciem playlistę B - działa bez zarzutu

Tak więc każde kliknięcie nr. 1, 3, 5, 7 etc. działa bez zarzutu, natomiast kliknięcia nr. 2, 4, 6, 8 nie działają, nie odtwarzają muzyki, nie ma również możliwości pauzowania i odpauzowania playlisty.

Kod:

<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <title>RADIO</title>
    <link rel="stylesheet" href="style2.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto&display=swap">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/all.min.css">
</head>
<body>
    <div id="menu">
        <div id="buttons">
            <div class="button-L" onclick="document.body.style.backgroundImage = 'url(img/1.jpg)';"><button value="W" onclick="gra(this)">Playlista 1</button></div>
            <div class="button-S" onclick="document.body.style.backgroundImage = 'url(img/2.jpg)';"><button value="W1" onclick="gra(this)">Playlista 2</button></div>
            <div class="button-S" onclick="document.body.style.backgroundImage = 'url(img/3.jpg)';"><button value="W2" onclick="gra(this)">Playlista 3</button></div>
            <div class="button-S" onclick="document.body.style.backgroundImage = 'url(img/4.jpg)';"><button value="W3" onclick="gra(this)">Playlista 4</button></div>
        </div>
    </div>

    <div class="music-container" id="music-container">
        <div class="music-info">
          <h4 id="title"></h4>
          <div class="progress-container" id="progress-container">
            <div class="progress" id="progress"></div>
          </div>
        </div>
  
        <audio src="music/sport.mp3" id="audio"></audio>
  
        <div class="img-container">
          <img src="img/cd-w3.jpg" alt="music-cover" id="cover">
        </div>

        <div class="navigation">
          <button id="prev" class="action-btn">
            <i class="fas fa-backward"></i>
          </button>

          <button id="play" class="action-btn action-btn-big">
            <i class="fas fa-play"></i>
          </button>

          <button id="next" class="action-btn">
            <i class="fas fa-forward"></i>
          </button>
        </div>
      </div>

    <script type="text/javascript">
        function gra(tytul) {
            var tytulGry = tytul.value;
            var songs = [];
            
            // Song titles
            if(tytulGry === "W") songs = ['The Trail', 'Kaer Morhen'];
            else if(tytulGry === "W1") songs = ['After The Storm', 'Spikeroog'];
            else if(tytulGry === "W2") songs = ['Trauma', 'Foxkids'];
            else if(tytulGry === "W3") songs = ['Myspace', 'Sport'];
        
            const musicContainer = document.getElementById('music-container');
            const playBtn = document.getElementById('play');
            const prevBtn = document.getElementById('prev');
            const nextBtn = document.getElementById('next');

            const audio = document.getElementById('audio');
            const progress = document.getElementById('progress');
            const progressContainer = document.getElementById('progress-container');
            const title = document.getElementById('title');
            const cover = document.getElementById('cover');
            const currTime = document.querySelector('#currTime');
            const durTime = document.querySelector('#durTime')
            
            // Keep track of song
            let songIndex = 1;

            // Initially load song details into DOM
            loadSong(songs[songIndex]);

            // Update song details
            function loadSong(song) {
            title.innerText = song;
            audio.src = `music/`+song+`.mp3`;
            cover.src = `img/`+tytulGry+`.jpg`;
            }

            // Play song
            function playSong() {
            musicContainer.classList.add('play');
            playBtn.querySelector('i.fas').classList.remove('fa-play');
            playBtn.querySelector('i.fas').classList.add('fa-pause');

            audio.play();
            }

            // Pause song
            function pauseSong() {
            musicContainer.classList.remove('play');
            playBtn.querySelector('i.fas').classList.add('fa-play');
            playBtn.querySelector('i.fas').classList.remove('fa-pause');

            audio.pause();
            }

            // Previous song
            function prevSong() {
            songIndex--;

            if (songIndex < 0) {
                songIndex = songs.length - 1;
            }

            loadSong(songs[songIndex]);

            playSong();
            }

            // Next song
            function nextSong() {
            songIndex++;

            if (songIndex > songs.length - 1) {
                songIndex = 0;
            }

            loadSong(songs[songIndex]);

            playSong();
            }

            // Update progress bar
            function updateProgress(e) {
            const { duration, currentTime } = e.srcElement;
            const progressPercent = (currentTime / duration) * 100;
            progress.style.width = `${progressPercent}%`;
            }

            // Set progress bar
            function setProgress(e) {
            const width = this.clientWidth;
            const clickX = e.offsetX;
            const duration = audio.duration;

            audio.currentTime = (clickX / width) * duration;
            }

            //get duration & currentTime for Time of song
            function DurTime (e) {
                const {duration,currentTime} = e.srcElement;
                var sec;
                var sec_d;

                // define minutes currentTime
                let min = (currentTime==null)? 0:
                Math.floor(currentTime/60);
                min = min <10 ? '0'+min:min;

                // define seconds currentTime
                function get_sec (x) {
                    if(Math.floor(x) >= 60){
                        
                        for (var i = 1; i<=60; i++){
                            if(Math.floor(x)>=(60*i) && Math.floor(x)<(60*(i+1))) {
                                sec = Math.floor(x) - (60*i);
                                sec = sec <10 ? '0'+sec:sec;
                            }
                        }
                    }else{
                        sec = Math.floor(x);
                        sec = sec <10 ? '0'+sec:sec;
                    }
                } 

                get_sec (currentTime,sec);

                // change currentTime DOM
                currTime.innerHTML = min +':'+ sec;

                // define minutes duration
                let min_d = (isNaN(duration) === true)? '0':
                    Math.floor(duration/60);
                min_d = min_d <10 ? '0'+min_d:min_d;


                function get_sec_d (x) {
                    if(Math.floor(x) >= 60){
                        
                        for (var i = 1; i<=60; i++){
                            if(Math.floor(x)>=(60*i) && Math.floor(x)<(60*(i+1))) {
                                sec_d = Math.floor(x) - (60*i);
                                sec_d = sec_d <10 ? '0'+sec_d:sec_d;
                            }
                        }
                    }else{
                        sec_d = (isNaN(duration) === true)? '0':
                        Math.floor(x);
                        sec_d = sec_d <10 ? '0'+sec_d:sec_d;
                    }
                } 

                // define seconds duration
                
                get_sec_d (duration);

                // change duration DOM
                durTime.innerHTML = min_d +':'+ sec_d;
                    
            };

            // Event listeners
            playBtn.addEventListener('click', () => {
            const isPlaying = musicContainer.classList.contains('play');

            if (isPlaying) {
                pauseSong();
            } else {
                playSong();
            }
            });

            // Change song
            prevBtn.addEventListener('click', prevSong);
            nextBtn.addEventListener('click', nextSong);

            // Time/song update
            audio.addEventListener('timeupdate', updateProgress);

            // Click on progress bar
            progressContainer.addEventListener('click', setProgress);

            // Song ends
            audio.addEventListener('ended', nextSong);

            // Time of song
            audio.addEventListener('timeupdate',DurTime);
        }
    </script>
</body>
</html>

Piosenki są plikami .mp3, których nazwy są przechowywane w zmiennej songs[]; Gdzie leży źródło problemu? Liczę na odpowiedź.

Pozdrawiam.

1
komentarz 13 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 14 lutego 2022 przez VBService

Nie udało Mi się odtworzyć Twojego problemu (może brak pełnej wersji strony wink). Szybko sobie "odpuściłem", ale w oparciu o Twój kod na szybko "naskrobałem" takie coś ... smiley, może się Tobie przyda coś z tego.

 

propozycja / przykład  (linki do obrazków i plików mp3 - dla demonstracji)

const songs = [
  { //       'img/1.jpg'
    'bg_img':'https://picsum.photos/1500/1500/?random=1', 'title':'India', 
    'list': [
      {  //    'music/The Trail.mp3'
        'link':'https://freesound.org/data/previews/350/350547_347704-lq.mp3',
        'title':'Kaiho - india sitar',
        //            'img/'+tytulGry+'.jpg'
        //            'img/cd-w3.jpg'
        'cover_front':'https://picsum.photos/50/50/?random=10',
        'cover_back':'https://picsum.photos/50/50/?random=101'
      },
      {  //    'music/Kaer Morhen.mp3'
        'link':'https://freesound.org/data/previews/37/37715_347704-lq.mp3',
        'title':'Kaiho - india sitar tarb 12strings',
        'cover_front':'https://picsum.photos/50/50/?random=11',
        'cover_back':'https://picsum.photos/50/50/?random=111'
      }
    ]},
  { //       'img/2.jpg'
    'bg_img':'https://picsum.photos/1500/1500/?random=2', 'title':'Fantasy', 
    'list': [
      {  //    'music/After The Storm.mp3'
        'link':'https://freesound.org/data/previews/264/264295_4019029-lq.mp3',
        'title':'Autor1 - fantasy1',
        'cover_front':'https://picsum.photos/50/50/?random=20',
        'cover_back':'https://picsum.photos/50/50/?random=201'
      },
      {  //    'music/Spikeroog.mp3'
        'link':'https://freesound.org/data/previews/511/511311_6627602-lq.mp3',
        'title':'Fantasy długa nazwa bez znaku pauzy',
        'cover_front':'https://picsum.photos/50/50/?random=21',
        'cover_back':'https://picsum.photos/50/50/?random=211'
      },
      {  //    'music/Spikeroog-2.mp3'
        'link':'https://freesound.org/data/previews/321/321220_418555-lq.mp3',
        'title':'Tawerna',
        'cover_front':'https://picsum.photos/50/50/?random=22',
        'cover_back':'https://picsum.photos/50/50/?random=221'
      }
    ]},
  { //       'img/3.jpg'
    'bg_img':'https://picsum.photos/1500/1500/?random=3', 'title':'80s game music', 
    'list': [
      {  //    'music/Trauma.mp3'
        'link':'https://freesound.org/data/previews/569/569628_2019171-lq.mp3',
        'title':'Autor2 - 80s game music',
        'cover_front':'https://picsum.photos/50/50/?random=30',
        'cover_back':'https://picsum.photos/50/50/?random=301'
      },
      {  //    'music/Foxkids.mp3'
        'link':'https://freesound.org/data/previews/569/569627_2019171-lq.mp3',
        'title':'Autor2 - 80s game music HQ',
        'cover_front':'https://picsum.photos/50/50/?random=31',
        'cover_back':'https://picsum.photos/50/50/?random=311'
      },
      {  //    'music/Foxkids_cover.mp3'
        'link':'https://freesound.org/data/previews/177/177088_3042558-lq.mp3',
        'title':'Group X2 - Commodore dream',
        'cover_front':'https://picsum.photos/50/50/?random=32',
        'cover_back':'https://picsum.photos/50/50/?random=321'
      }
    ]},
  { //       'img/4.jpg'
    'bg_img':'https://picsum.photos/1500/1500/?random=4', 'title':'Nature', 
    'list': [
      {  //    'music/Myspace.mp3'
        'link':'https://freesound.org/data/previews/48/48412_553671-lq.mp3',
        'title':'relax-the sea waves',
        'cover_front':'https://picsum.photos/50/50/?random=40',
        'cover_back':'https://picsum.photos/50/50/?random=401'
      },
      {  //    'music/Sport.mp3'
        'link':'https://freesound.org/data/previews/511/511311_6627602-lq.mp3',
        'title':'', // pusty też może  być ;-)
        'cover_front':'https://picsum.photos/50/50/?random=41',
        'cover_back':'https://picsum.photos/50/50/?random=411'
      }
    ]}
];

let playlist_buttons_container, music_container, audio, 
    button_play, button_pause, button_prev, button_next;

window.addEventListener('load', load);

function load() {
  /* 
    korzystając z faktu, że w javascript "występuje mechanizm" Event Delegation.
    https://davidwalsh.name/event-delegate
  */
  playlist_buttons_container = document.querySelector('#menu #buttons');
  playlist_buttons_container.addEventListener('click', startPlaylist);
  /* ------------------------------------------------------------------------ */

  loadPlaylistButton();

  audio = document.querySelector('#audio');
  audio.addEventListener('ended', _=> {
    audio.dataset.isPlayed = true;
    songChangeOnPlaylist(+1); 
  });
  audio.addEventListener('play', songStartedPlay);
  audio.addEventListener('pause', songHasPaused);

  music_container = document.querySelector('#music-container');
  button_play  = music_container.querySelector('#play');
  button_pause = music_container.querySelector('#pause');
  button_prev  = music_container.querySelector('#prev');
  button_next  = music_container.querySelector('#next');  

  button_play.addEventListener('click', songPlay);
  button_pause.addEventListener('click', songPause);

  button_prev.addEventListener('click', _=> { songChangeOnPlaylist(-1); });
  button_next.addEventListener('click', _=> { songChangeOnPlaylist(+1); });
}

function startPlaylist(e) {
  if (e.target && e.target.nodeName == 'BUTTON') {
    const playlist_index = e.target.id;

    audioButtonOff('play');

    setBodyBackground(songs[playlist_index].bg_img);
    setPlaylistIndex(playlist_index);
    setPlaylistLength(songs[playlist_index].list.length);
    setSongIndex(0);
    songLoad();
    setSongTitle();
    setSongImageCover();

    if (audio.dataset.isPlayed === 'true') songPlay();
  }
}

function setBodyBackground(image) {
  document.body.style.backgroundImage = 'url('+image+')';
}

function songLoad() {
  try {
    const playlist_index = getPlaylistIndex(),
          song_index = getSongIndex();

    audio.src = songs[playlist_index].list[song_index].link;
    if (audio.dataset.isPlayed === 'true') songPlay();
  } catch(err) {
    console.warn('songLoad:\n' + err.message);
  } 
}
function songPlay() {
  if (audio.src !== '')     
    audio.play();
}
function songStartedPlay() {
  audioButtonOn('play');
  audio.dataset.isPlayed = true;
}
function songPause() {
  audio.pause();
}
function songHasPaused() {
  audioButtonOff('play');
  audio.dataset.isPlayed = false;
}
function songHasChangeOnPlaylist() {
  songLoad();
  setSongTitle();
  setSongImageCover();
}

function songChangeOnPlaylist(direction) {
  try {
    const playlist_length = getPlaylistLength();
    let song_index = getSongIndex();

    if (!isNaN(song_index) && !isNaN(playlist_length)) {
      song_index += direction;
      song_index = (song_index < 0) ? playlist_length : (song_index > playlist_length) ? 0 : song_index;
      setSongIndex(song_index);
      songHasChangeOnPlaylist();
    } else { throw 'The song index has not been set'; }
  } catch(err) {
    console.warn('songChangeOnPlayList:\n' + err.message);
  }
}
function setPlaylistIndex(index) {
  audio.dataset.playlistIndex = index;  
}
function getPlaylistIndex() {
  return parseInt(audio.dataset.playlistIndex);  
}
function setPlaylistLength(length) {
  audio.dataset.playlistLength = length;  
}
function getPlaylistLength(length) {
  return parseInt(audio.dataset.playlistLength) - 1 || 0;  
}
function setSongIndex(index) {
  audio.dataset.songIndex = index;  
}
function getSongIndex() {
  return parseInt(audio.dataset.songIndex) || 0;  
}
function setSongTitle() {
  try {
    const song_title_container = music_container.querySelector('#title'),
          playlist_index = getPlaylistIndex(),
          song_index = getSongIndex();
    let song_title = songs[playlist_index].list[song_index].title;

    if (song_title.trim()) {
      if (song_title.includes('-')) {
        song_title = song_title.charAt(0).toUpperCase() + song_title.slice(1);
        song_title = song_title.split('-')[0].trim() + '-' 
          + song_title.split('-')[1].trim().charAt(0).toUpperCase()
          + song_title.split('-')[1].trim().slice(1);
        song_title = song_title.replace('-', '<br />');

        song_title_container.style.lineHeight = '';
        song_title_container.innerHTML = song_title;
      } else {
        song_title = song_title.charAt(0).toUpperCase() + song_title.slice(1);
        song_title_container.style.lineHeight = '2.25em';
        song_title_container.textContent = song_title;
      } 
    } else {
      song_title_container.innerHTML = '';
    }
  } catch(err) {
    console.warn('setSongTitle:\n' + err.message);
  }
}
function setSongImageCover() {
  try {
    const song_image_cover_front = music_container.querySelector('#image-cover-front'),
          song_image_cover_back = music_container.querySelector('#image-cover-back'),
          playlist_index = getPlaylistIndex(),
          song_index = getSongIndex();

    const song_image_front = songs[playlist_index].list[song_index].cover_front,
          song_image_back = songs[playlist_index].list[song_index].cover_back;

    // https://stackoverflow.com/questions/5775469/whats-the-valid-way-to-include-an-image-with-no-src
    const empty = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';

    if (!song_image_front.trim()) song_image_front = empty;
    if (!song_image_back.trim()) song_image_back = empty;

    song_image_cover_front.src = song_image_front;
    song_image_cover_back.src = song_image_back;
  } catch(err) {
    console.warn('setSongImageCover:\n' + err.message);
  }
}

function audioButtonOn(button) {
  if (button == 'play')
    button_play.classList.add('button_audio_on');    
}

function audioButtonOff(button) {
  if (button == 'play')
    button_play.classList.remove('button_audio_on');
}

function loadPlaylistButton() {
  if (songs.length) { // true wartość większa od zera ;-)
    for (let i=0; i<songs.length; i++) {
      const div = document.createElement('DIV'),
            button = document.createElement('BUTTON');      

      button.id = i;
      button.textContent = songs[i].title;
      div.classList.add('button-L');
      div.appendChild(button);

      playlist_buttons_container.appendChild(div);
    }
  }
}

/* --------------------------------------------------------------------- */
// To z twojego kodu zostało jeszcze do zaadoptowania
function gra() {
  const progress = document.getElementById('progress');
  const progressContainer = document.getElementById('progress-container');
  const currTime = document.querySelector('#currTime');
  const durTime = document.querySelector('#durTime');

  // Update progress bar
  function updateProgress(e) {
    const { duration, currentTime } = e.srcElement;
    const progressPercent = (currentTime / duration) * 100;
    progress.style.width = `${progressPercent}%`;
  }
  // Set progress bar
  function setProgress(e) {
    const width = this.clientWidth;
    const clickX = e.offsetX;
    const duration = audio.duration;

    audio.currentTime = (clickX / width) * duration;
  }

  //get duration & currentTime for Time of song
  function DurTime (e) {
    const {duration,currentTime} = e.srcElement;
    var sec;
    var sec_d;

    // define minutes currentTime
    let min = (currentTime==null)? 0:
    Math.floor(currentTime/60);
    min = min <10 ? '0'+min:min;

    // define seconds currentTime
    function get_sec (x) {
      if(Math.floor(x) >= 60){

        for (var i = 1; i<=60; i++){
          if(Math.floor(x)>=(60*i) && Math.floor(x)<(60*(i+1))) {
            sec = Math.floor(x) - (60*i);
            sec = sec <10 ? '0'+sec:sec;
          }
        }
      }else{
        sec = Math.floor(x);
        sec = sec <10 ? '0'+sec:sec;
      }
    } 

    get_sec (currentTime,sec);
    // change currentTime DOM
    currTime.innerHTML = min +':'+ sec;
    // define minutes duration
    let min_d = (isNaN(duration) === true)? '0':
    Math.floor(duration/60);
    min_d = min_d <10 ? '0'+min_d:min_d;

    function get_sec_d (x) {
      if(Math.floor(x) >= 60){

        for (var i = 1; i<=60; i++){
          if(Math.floor(x)>=(60*i) && Math.floor(x)<(60*(i+1))) {
            sec_d = Math.floor(x) - (60*i);
            sec_d = sec_d <10 ? '0'+sec_d:sec_d;
          }
        }
      }else{
        sec_d = (isNaN(duration) === true)? '0':
        Math.floor(x);
        sec_d = sec_d <10 ? '0'+sec_d:sec_d;
      }
    } 

    // define seconds duration
    get_sec_d (duration);
    // change duration DOM
    durTime.innerHTML = min_d +':'+ sec_d;
  }

  // Time/song update
  audio.addEventListener('timeupdate', updateProgress);
  // Click on progress bar
  progressContainer.addEventListener('click', setProgress);
  // Time of song
  audio.addEventListener('timeupdate',DurTime);
}

 

demonstracyjny html + css poniżej

1
komentarz 13 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 14 lutego 2022 przez VBService
<!DOCTYPE html>
<html lang="pl">
  <head>
    <meta charset="UTF-8">
    <title>RADIO</title>
    <link rel="stylesheet" href="style2.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto&display=swap">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/all.min.css">

    <style>
      * {
        box-sizing: border-box;
      }
      body {
        width: 100vw;
        background-position: center center;
        background-size: cover;
        background-repeat: no-repeat;
        transition: background-image 1s;
        overflow: hidden;
      }
      body button {
        border-radius: 0.5em;
        user-select: none;
        cursor: pointer;
      }
      #menu #buttons button {
        width: 12em;
        margin: 0.2em 0;
      }
      #music-container #title {
        background-color: rgba(0,0,0,0.6);
        color: limegreen;
        padding: 0.2em;
        width: 10em;
        height: 2.6em;  
        overflow: hidden;
        white-space: pre;
        text-overflow: ellipsis; /* dodaje 3 kropki ... */
        text-align: center;
      }
      #music-container #image-cover {
        width: 60px;
        height: 60px;
        background-size: cover;
        background-repeat: no-repeat;
        transition: background-image 1s;
      }
      #music-container button {
        color: black;  
        transition: color 0.2s;
      }
      #music-container button:active {
        color: #00C000;
      }
      #music-container .button_audio_on {
        color: #00C000;
      }
    </style>
  </head>
  <body>
    <div id="menu">
      <div id="buttons"></div>
    </div>

    <div class="music-container" id="music-container">
      <div class="music-info">
        <h4 id="title"></h4>
        <div class="progress-container" id="progress-container">
          <div class="progress" id="progress"></div>
        </div>
      </div>

      <audio id="audio"></audio>

      <div class="img-container">
        <!--
        <img src="img/default.jpg" alt="music-cover-front" id="image-cover-front">
        <img src="img/default.jpg" alt="music-cover-back" id="image-cover-back">
        -->

        <!--
            https://stackoverflow.com/questions/5775469/whats-the-valid-way-to-include-an-image-with-no-src
        -->
        <img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" alt="music-cover-front" id="image-cover-front">
        <img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" alt="music-cover-back" id="image-cover-back">        
      </div>

      <div class="navigation">
        <button id="prev" class="action-btn">
          <i class="fas fa-backward"></i>
        </button>

        <button id="play" class="action-btn action-btn-big">
          <i class="fas fa-play"></i>
        </button>

        <button id="pause" class="action-btn action-btn-big">
          <i class="fas fa-pause"></i>
        </button>

        <button id="next" class="action-btn">
          <i class="fas fa-forward"></i>
        </button>
      </div>
    </div>
  </body>
</html>

 

1
komentarz 14 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 14 lutego 2022 przez VBService

Problem chyba leży w tym, że wszystkie funkcje umieściłeś w scope-ie funkcji

function gra(tytul) {
   ...
}

javascript dopuszcza umieszczanie w funkcji innych funkcji w jej "wnętrzu" (dlatego nie pokazuje błędów w konsoli), ale generalnie inne (wszystkie) funkcje powinny znajdować w Global scope, czyli np. w Twoim przypadku 

// zmienne globalne
var songs = [];

window.addEventListener('load', load);
function load {
   // funkcja uruchamiana po "załadowaniu" strony
   // ustawianie początkowych parametrów itp.
   ...
}

function gra(tytul) {
   ...
   // Song titles
   if(tytulGry === "W") songs = ['The Trail', 'Kaer Morhen'];
    else if(tytulGry === "W1") songs = ['After The Storm', 'Spikeroog'];
    else if(tytulGry === "W2") songs = ['Trauma', 'Foxkids'];
    else if(tytulGry === "W3") songs = ['Myspace', 'Sport'];
   ...
   loadSong(songs[songIndex]);
   ...       
}

function loadSong(song) {
  ...
  audio.src = "music/" + song + ".mp3";
  ...
}

function playSong() {
    ...
}

itd.

 

1
komentarz 16 lutego 2022 przez CanoNee Nowicjusz (230 p.)
edycja 16 lutego 2022 przez CanoNee

Dziękuję bardzo za pomoc! Po przeniesieniu poniższych linijek...

// Tablica przechowująca utwory w zależności od wybranej kategorii
var songs = [];

// Panel sterujący odtwarzacza audio
const musicContainer = document.getElementById('music-container');
const playBtn = document.getElementById('play');
const prevBtn = document.getElementById('prev');
const nextBtn = document.getElementById('next');

// Informacje o piosence
const audio = document.getElementById('audio');
const progress = document.getElementById('progress');
const progressContainer = document.getElementById('progress-container');
const title = document.getElementById('title');
const cover = document.getElementById('cover');
const currTime = document.querySelector('#currTime');
const durTime = document.querySelector('#durTime')
const range = document.querySelector('#volume-control');
    
// Domyślny indeks piosenki z tablicy
let songIndex = 0;

...poza jakąkolwiek funkcję (tj. jako zmienne globalne), skrócenie "głównej funkcji" gra(tytul) {} tak, aby nie zawierała w sobie żadnych podfunkcji, tzn...

function gra(tytul) {
    // Zmienna przechowująca informację o wybranej przez użytkownika stacji
    var tytulGry = tytul.value;
    
    // Playlisty w zależności od wybranej stacji
    if(tytulGry === "W") { songs = ['Myspace']; 
        document.body.style.backgroundImage = 'url(img/W.jpg)'; }
    else if(tytulGry === "W1") { songs = ['Nowy Sobel', 'Sobel - Liczba 7'];
        document.body.style.backgroundImage = 'url(img/W1.jpg)'; }
    else if(tytulGry === "W2") { songs = ['Vergen by Night', 'Elaine Ettariel', 'Assassins of Kings', 'Tough Times', 'A Watering Hole in the Harbor', 'The Assassin Looms', 'A Tavern on the Riverbank', 'Flotsam at Sunrise', 'Ladybug'];
        document.body.style.backgroundImage = 'url(img/W2.jpg)'; }
    else if(tytulGry === "W3") { songs = ['The Trail', 'Kaer Morhen', 'After The Storm', 'Spikeroog'];
        document.body.style.backgroundImage = 'url(img/W3.jpg)'; }

    // Wywołanie funkcji ładującej piosenki na podstawie playlisty
    loadSong(songs[songIndex]);
}

...odtwarzanie playlist działa bez zarzutu, mogę klikać pojedynczo na każdą playlistę i wszystko działa, jednak przy dojściu piosenki do końca playlista się zawiesza, nie odtwarza następnej piosenki. Przewinięcie również nie działa tj. działa, aczkolwiek trzeba zapauzować i odpauzować, aby piosenka poleciała.

Nie udało Mi się odtworzyć Twojego problemu (może brak pełnej wersji strony wink).

W poście zawarłem całą stronę, nie zawarłem tylko pliku .css, ale to ze względu na brak możliwości przekazania obrazów i plików .mp3. Strona była na etapie budowy, dlatego nie zawarłem w kodzie szczegółów, które nie dotyczyły problemu. Poniżej prezentuję kod w obecnej formie:

// Tablica przechowująca utwory w zależności od wybranej kategorii
var songs = [];

// Panel sterujący odtwarzacza audio
const musicContainer = document.getElementById('music-container');
const playBtn = document.getElementById('play');
const prevBtn = document.getElementById('prev');
const nextBtn = document.getElementById('next');

// Informacje o piosence
const audio = document.getElementById('audio');
const progress = document.getElementById('progress');
const progressContainer = document.getElementById('progress-container');
const title = document.getElementById('title');
const cover = document.getElementById('cover');
const currTime = document.querySelector('#currTime');
const durTime = document.querySelector('#durTime')
const range = document.querySelector('#volume-control');
    
// Domyślny indeks piosenki z tablicy
var songIndex = 0;

function gra(tytul) {
    // Zmienna przechowująca informację o wybranej przez użytkownika stacji
    var tytulGry = tytul.value;
    
    // Playlisty w zależności od wybranej stacji
    if(tytulGry === "W") { songs = ['Myspace']; 
        document.body.style.backgroundImage = 'url(img/W.jpg)'; }
    else if(tytulGry === "W1") { songs = ['Nowy Sobel', 'Sobel - Liczba 7'];
        document.body.style.backgroundImage = 'url(img/W1.jpg)'; }
    else if(tytulGry === "W2") { songs = ['Vergen by Night', 'Elaine Ettariel', 'Assassins of Kings', 'Tough Times', 'A Watering Hole in the Harbor', 'The Assassin Looms', 'A Tavern on the Riverbank', 'Flotsam at Sunrise', 'Ladybug'];
        document.body.style.backgroundImage = 'url(img/W2.jpg)'; }
    else if(tytulGry === "W3") { songs = ['The Trail', 'Kaer Morhen', 'After The Storm', 'Spikeroog'];
        document.body.style.backgroundImage = 'url(img/W3.jpg)'; }

    // Wywołanie funkcji ładującej piosenki na podstawie playlisty
    loadSong(songs[songIndex]);
}

// Aktualizacja informacji o piosence
function loadSong(song) {
    title.innerText = song; // Tytuł
    audio.src = `music/`+song+`.mp3`; // Ścieżka dźwiękowa
    cover.src = `img/cd-`+tytulGry+`.jpg`; // Okładka albumu
}

// Funkcja odtwarzająca piosenki
function playSong() {
    musicContainer.classList.add('play');
    playBtn.querySelector('i.fas').classList.remove('fa-play');
    playBtn.querySelector('i.fas').classList.add('fa-pause');

    audio.play();
}

// Funkcja pauzująca piosenki
function pauseSong() {
    musicContainer.classList.remove('play');
    playBtn.querySelector('i.fas').classList.add('fa-play');
    playBtn.querySelector('i.fas').classList.remove('fa-pause');

    audio.pause();
}

// Funkcja odtwarzająca poprzednią piosenkę
function prevSong() {
    songIndex--;

    // Jeśli indeks piosenki wyjdzie ujemny przejdź na koniec tablicy
    if (songIndex < 0) {
        songIndex = songs.length - 1;
    }

    loadSong(songs[songIndex]);

    playSong();
}

// Funkcja odtwarzająca następną piosenkę
function nextSong() {
    songIndex++;

    // Jeśli indeks piosenki wyjdzie poza tablicę wróć na jej początek
    if (songIndex > songs.length - 1) {
        songIndex = 0;
    }

    loadSong(songs[songIndex]);

    playSong();
}

// Funkcja aktualizująca pasek postępu piosenki
function updateProgress(e) {
    const { duration, currentTime } = e.srcElement;
    const progressPercent = (currentTime / duration) * 100;
    progress.style.width = `${progressPercent}%`;
}

// Funkcja obliczająca pasek postępu
function setProgress(e) {
    const width = this.clientWidth;
    const clickX = e.offsetX;
    const duration = audio.duration;

    audio.currentTime = (clickX / width) * duration;
}

// Funkcja odpowiedzialna za kontrolę głośności piosenki
var volume = document.querySelector("#volume-control");
volume.addEventListener("change", (e) => {
    audio.volume = e.currentTarget.value / 100;
})

// Funkcja obliczająca długość piosenki oraz obecnie odtwarzany moment piosenki
function DurTime (e) {
    const {duration,currentTime} = e.srcElement;
    var sec;
    var sec_d;

    // Przelicz na minuty funkcji currentTime
    let min = (currentTime==null)? 0:
    Math.floor(currentTime/60);
    min = min <10 ? '0'+min:min;

    // Oblicz sekundy funkcji currentTime
    function get_sec (x) {
        if(Math.floor(x) >= 60){
                
            for (var i = 1; i<=60; i++){
                if(Math.floor(x)>=(60*i) && Math.floor(x)<(60*(i+1))) {
                    sec = Math.floor(x) - (60*i);
                    sec = sec <10 ? '0'+sec:sec;
                }
            }
        }else{
            sec = Math.floor(x);
            sec = sec <10 ? '0'+sec:sec;
        }
    } 

    get_sec (currentTime,sec);

    // Zmień currentTime DOM
    currTime.innerHTML = min +':'+ sec;

    // Oblicz długość piosenki (minuty)
    let min_d = (isNaN(duration) === true)? '0':
        Math.floor(duration/60);
    min_d = min_d <10 ? '0'+min_d:min_d;

    // Oblicz długość piosenki (sekundy)
    function get_sec_d (x) {
        if(Math.floor(x) >= 60){
                
            for (var i = 1; i<=60; i++){
                if(Math.floor(x)>=(60*i) && Math.floor(x)<(60*(i+1))) {
                    sec_d = Math.floor(x) - (60*i);
                    sec_d = sec_d <10 ? '0'+sec_d:sec_d;
                }
            }
        }else{
            sec_d = (isNaN(duration) === true)? '0':
            Math.floor(x);
            sec_d = sec_d <10 ? '0'+sec_d:sec_d;
        }
    } 

        // define seconds duration
        get_sec_d (duration);

        // change duration DOM
        durTime.innerHTML = min_d +':'+ sec_d;
            
    };

    // Nasłuchiwanie zdarzeń
    playBtn.addEventListener('click', () => {
    const isPlaying = musicContainer.classList.contains('play');

    if (isPlaying) {
        pauseSong();
    } else {
        playSong();
    }
    });

// Zmień piosenkę na poprzednią/następną
prevBtn.addEventListener('click', prevSong);
nextBtn.addEventListener('click', nextSong);

// Zaktualizuj czas piosenki
audio.addEventListener('timeupdate', updateProgress);

// Możliwość przewijania piosenki na pasku postępu
progressContainer.addEventListener('click', setProgress);

// Gdy piosenka się skończy puść następną
audio.addEventListener('ended', nextSong);

// Oblicz czas piosenki
audio.addEventListener('timeupdate',DurTime);

 

1
komentarz 16 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 17 lutego 2022 przez VBService

W funkcji gra() masz lokalną zmienną tytulGry, do której odwołujesz się też w loadSong

u Mnie pokazuje taki błąd

 

[ UPDATE ]

ale to nie jest błąd jedyny który powoduje, że

// Gdy piosenka się skończy puść następną
audio.addEventListener('ended', nextSong);

nie działa do końca prawidłowo

funkcja nextSong()

// Funkcja odtwarzająca następną piosenkę
function nextSong() {
    songIndex++;
 
    // Jeśli indeks piosenki wyjdzie poza tablicę wróć na jej początek
    if (songIndex > songs.length - 1) {
        songIndex = 0;
    }
 
    loadSong(songs[songIndex]);
 
    playSong();
}

 

przenieś playSong() z nextSong() do loadSong()

czyli

// Funkcja odtwarzająca następną piosenkę
function nextSong() {
    songIndex++;
 
    // Jeśli indeks piosenki wyjdzie poza tablicę wróć na jej początek
    if (songIndex > songs.length - 1) songIndex = 0;
 
    loadSong(songs[songIndex]);   
}

tak jak masz tutaj

    playBtn.addEventListener('click', () => {
    const isPlaying = musicContainer.classList.contains('play');
 
    if (isPlaying) {
        pauseSong();
    } else {
        playSong();
    }
    });

czyli

function loadSong(song) {
    title.innerText = song; // Tytuł
    audio.src = `music/`+song+`.mp3`; // Ścieżka dźwiękowa
    cover.src = `img/cd-`+tytulGry+`.jpg`; // Okładka albumu

   const isPlaying = musicContainer.classList.contains('play'); 
    if (isPlaying) playSong();
}

no i popraw np. tak loadSong() w kwestii tej zmiennej tytulGry

czyli

function gra(tytul) {
    // Zmienna przechowująca informację o wybranej przez użytkownika stacji
    var tytulGry = tytul.value;
     
    // Playlisty w zależności od wybranej stacji
    if(tytulGry === "W") { songs = ['https://freesound.org/data/previews/264/264295_4019029-lq.mp3']; 
        document.body.style.backgroundImage = 'url(img/W.jpg)'; }
    else if(tytulGry === "W1") { songs = ['Nowy Sobel', 'Sobel - Liczba 7'];
        document.body.style.backgroundImage = 'url(img/W1.jpg)'; }
    else if(tytulGry === "W2") { songs = ['Vergen by Night', 'Elaine Ettariel', 'Assassins of Kings', 'Tough Times', 'A Watering Hole in the Harbor', 'The Assassin Looms', 'A Tavern on the Riverbank', 'Flotsam at Sunrise', 'Ladybug'];
        document.body.style.backgroundImage = 'url(img/W2.jpg)'; }
    else if(tytulGry === "W3") { songs = ['The Trail', 'Kaer Morhen', 'After The Storm', 'Spikeroog'];
        document.body.style.backgroundImage = 'url(img/W3.jpg)'; }
 
    // Wywołanie funkcji ładującej piosenki na podstawie playlisty
    loadSong(songs[songIndex], tytulGry);
}

function loadSong(song, tytulGry = "") {
    title.innerText = song; // Tytuł
    audio.src = `music/`+song+`.mp3`; // Ścieżka dźwiękowa

    if (tytulGry) // gdy  tytulGry = "" - false, gdy coś zawiera true, wtedy ładuje się okładka ;-)
        cover.src = `img/cd-`+tytulGry+`.jpg`; // Okładka albumu

   const isPlaying = musicContainer.classList.contains('play'); 
    if (isPlaying) playSong();
}

taki zapis

function loadSong(song, tytulGry = "") { ...}

powoduje, że możesz wywołać loadSong()

loadSong(someValue1, someValue2)

lub

loadSong(someValue1)

wtedy someValue2 jest ustawiane na wartość domyślną
w tym przypadku na pusty string

function loadSong(song, tytulGry = "")

 

1
komentarz 17 lutego 2022 przez VBService Ekspert (253,420 p.)

Sprawdź UPDATEsmiley

1
komentarz 17 lutego 2022 przez CanoNee Nowicjusz (230 p.)

W funkcji gra() masz lokalną zmienną tytulGry, do której odwołujesz się też w loadSong

Sprawdziłem to i w zasadzie zmienna var tytulGry umieszczona w funkcji gra(tytul) powodowała ten problem, nic więcej nie zmieniłem, nie mam pojęcia dlaczego, wydawało mi się, że skoro w funkcji loadSong() zmienna ta używana jest wyłącznie do zmiany okładki płyty CD to nie będzie problemem, a jednak... Przeniosłem ją poza funkcje (tj. jako zmienna globalna), a w funkcji gra(tytul) nadaję jej tą samą wartość tytul.value i wszystko działa bez zarzutu. 

Wypróbuję jeszcze zasugerowane poprawki, z pewnością są one lepiej, poprawniej napisane, niż mój dotychczasowy kod. W każdym razie sam program działa, ileż ja krwi napsułem, ileż niecenzuralnych słów, a rozwiązaniem okazało się przeniesienie kilku linijek do zmiennych globalnych... laugh 

Bardzo dziękuję za pomoc! Naprawdę jestem pod wrażeniem, jeszcze dużo nauki przede mną laugh

1
komentarz 17 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 17 lutego 2022 przez VBService

Zmienne globalne "ułatwiają życie", ale też mają swoje "ciemne" oblicze.  smiley

zobacz ten kod

// Globalne
let value1 = 'value1 - globalna';
console.info('1 '+value1);

function a() {
  let value1 = 'value1 - lokalna';
  console.log('2 '+value1);
}

function b() {
  console.log('3 '+value1);
}

function c() {
  // Taka zmiana może przyprawić 
  // o ból głowy w szukaniu błędu
  value1 = 'value1 - globalna zmieniona';
  console.log('4 '+value1);  
}

a();
b();
c();

także trzeba je używać "rozważnie"  wink, lub np. korzystać do przechowywania wartości zmiennych, które "muszą przechodzić" między funkcjami, to nie jest jedyne rozwiązanie, ale Ja np. korzystam z dataset

 

pewnie zauważyłeś w Moim kodzie zapis

audio.dataset.isPlayed = true;

co skutkuje w html-u (DOM strony)

<audio data-is-played="true" ...>
if (audio.dataset.isPlayed === 'true') songPlay();

ty też podszedłeś do tego "sprytnie"

const isPlaying = musicContainer.classList.contains('play'); 

przez sprawdzenie konkretnej klasy css przypisanej do elementu.

1
komentarz 17 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 17 lutego 2022 przez VBService

Ten zapis nie jest błędny, ale taki zapis `` wykorzystuje się template strings czy też template literals.

audio.src = 'music/'+song+'.mp3';

audio.src = "music/"+song+".mp3";

audio.src = `music/${song}.mp3`;

lub coś na kształt "template"

<pre></pre>

<script>
  const pre = document.querySelector('pre');
  let song = 'Vergen by Night';
  
  const text1 = 'Mój ulubiony utwór to "<<song>>". Jest super!';
  console.log(text1.replace('<<song>>', song));
  pre.textContent = text1.replace('<<song>>', song);
  
  pre.textContent += '\n';
  
  const text2 = 'Mój ulubiony utwór to %song%. Jest super!';
  console.info(text2.replace('%song%', song));
  pre.textContent += text2.replace('%song%', song);
  
  pre.textContent += '\n';
  
  const text3 = 'Mój ulubiony utwór to *song*. Jest super!';
  song = '<b>Vergen by Night</b>';
  console.warn(text3.replace('*song*', song));
  pre.innerHTML += text3.replace('*song*', song);
</script>

 

1
komentarz 17 lutego 2022 przez CanoNee Nowicjusz (230 p.)

Zmienne globalne "ułatwiają życie", ale też mają swoje "ciemne" oblicze.  smiley

Zdecydowanie laugh. Absolutna racja, już widzę różnicę w zmiennych. Widząc taki błąd, że działa co drugie kliknięcie myślałem, że problem jest bezpośrednio z którąś funkcją, skoro (de facto) klikając na daną playlistę wywołujemy cały kod na nowo i z początku działa bez zarzutu, a okazało się, że błąd już jest na samym początku i jednak zmienne potrafią namieszać...

także trzeba je używać "rozważnie"  wink,

Problemem już na etapie pisania okazało się to, iż pracę rozpocząłem z jedną playlistą, inne chciałem dodać, gdy skrypt byłby już na etapie finalizacji. Napisałem kilkaset linijek, wszystko po drodze testowałem, wszystko mi działało, natomiast problemem okazało się już dodanie kolejnych playlist, myślałem, że wystarczy wyłącznie zmiana zawartości tablicy songs[] w zależności od wartości przekazanej z HTML'a. Powinienem był najpierw zrobić dwie playlisty i od razu testować każdą możliwą funkcjonalność, być może wtedy problem wyszedłby dużo wcześniej.

ty też podszedłeś do tego "sprytnie" 

przez sprawdzenie konkretnej klasy css przypisanej do elementu.

To prawda, zmiana DOM strony z pewnością jest bardziej profesjonalna, zmiana CSS jest raczej drogą na skróty, natomiast do tej pory robiłem mniejsze projekty, głównie dla siebie, zmiana CSS była więc dla mnie bardziej łopatologiczna. Z pewnością trzeba będzie się bardziej zagłębić w DOM strony dla przyszłych projektów wink.

Ten zapis nie jest błędny, ale taki zapis `` wykorzystuje się template strings czy też template literals.

audio.src = 'music/'+song+'.mp3';
 
audio.src = "music/"+song+".mp3";
 
audio.src = `music/${song}.mp3`;

Z początku chciałem skorzystać z interpolacji w tym miejscu, jednak szukając błędu próbowałem doszukać się i tam, więc zrezygnowałem z zapisu ${song} na rzecz +song+, jednak backticki `` pozostały, w głównej mierze przez nieuwagę, ale przyznam się, że nie przywiązywałem wtedy do tego aż tak wielkiej wartości frown.

Dziękuję bardzo za wyjaśnienie pewnych aspektów, za linki (z pewnością się przydadzą), a przede wszystkim za pomoc w rozwiązywaniu problemu! smiley​​​​​​​

komentarz 17 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 17 lutego 2022 przez VBService

To prawda, zmiana DOM strony z pewnością jest bardziej profesjonalna, zmiana CSS jest raczej drogą na skróty,

To nie jest zmiana DOM w takim znaczeniu a bardziej możliwość dodawania własnych atrybutów do elementów  DOM.

 

posłużę się przykładem z kodu odtwarzacza muzyki tutaj omawianego.

Zaraz po załadowaniu strony element <audio> wygląda tak

<audio id="audio"></audio>

po wybraniu utworu (przycisk z playlist-y)

<audio id="audio" 
       data-playlist-index="1" 
       data-playlist-length="3" 
       data-song-index="0" 
       src="https://freesound.org/data/previews/264/264295_4019029-lq.mp3">
</audio>

po przyciśnięciu przycisku play

<audio id="audio" 
       data-playlist-index="1" 
       data-playlist-length="3" 
       data-song-index="0" 
       data-is-played="true"
       src="https://freesound.org/data/previews/264/264295_4019029-lq.mp3">
</audio>

sam widzisz, że dataset jest bardzo "użyteczne" i w sumie proste w "obsłudze" (można atrybutów data-... dodać wiele), inny sposób to użycie localStorage.

 

Moim zdaniem zmienne globalne sprawdzają się w takich przypadkach:

- tablica (w Naszym przykładzie songs[])

const songs = [
  { 
    'bg_img':'https://picsum.photos/1500/1500/?random=1',
    'title':'India', 
    'list': [
      { 
        'link':'https://freesound.org/data/previews/350/350547_347704-lq.mp3',
        'title':'Kaiho - india sitar',
        'cover_front':'https://picsum.photos/50/50/?random=10',
        'cover_back':'https://picsum.photos/50/50/?random=101'
      },
      {
        'link':'https://freesound.org/data/previews/37/37715_347704-lq.mp3',
        'title':'Kaiho - india sitar tarb 12strings',
        'cover_front':'https://picsum.photos/50/50/?random=11',
        'cover_back':'https://picsum.photos/50/50/?random=111'
      }
  ]}, ... itd.

    ...
];

- zmienne przechowujące referencję do elementu DOM

let playlist_buttons_container, music_container, audio, 
     button_play, button_pause, button_prev, button_next;

window.addEventListener('load', load);

function load() {
  playlist_buttons_container = document.querySelector('#menu #buttons');
  playlist_buttons_container.addEventListener('click', startPlaylist);

  audio = document.querySelector('#audio');

  music_container = document.querySelector('#music-container');
  button_play  = music_container.querySelector('#play');
  button_pause = music_container.querySelector('#pause');
  button_prev  = music_container.querySelector('#prev');
  button_next  = music_container.querySelector('#next');  

  button_play.addEventListener('click', songPlay);
  button_pause.addEventListener('click', songPause);

  ... itd
}

 

komentarz 17 lutego 2022 przez VBService Ekspert (253,420 p.)
edycja 17 lutego 2022 przez VBService

a wracając do

zmiana CSS jest raczej drogą na skróty

sposób dobry, bo można

const isPlaying = musicContainer.classList.contains('play');
if (isPlaying) playSong();

ale "niebezpieczny", bo załóżmy taki scenariusz, dopiszesz 300-400 linii kodu w ciągu kolejnych 1-2 tygodni i zapomnisz o powyższym wpisie, a stwierdzisz, że chcesz dodać "ozdoby" w css-ie do musicContainer z poziomu kodu js-a i napiszesz funkcję

function demo() {
    if (warunek) {
        musicContainer.className = '';
        // jakiś kod
    }
}

i przy testach będziesz się "dziwił" dlaczego songPlay() nie działa prawidłowo.  wink przypisanie 'play' do <audio> za pomocą audio.dataset.play jest bardziej odporne na tego typu "wpadki". Jedno trzeba mieć na uwadze wartości w data-... są "przechowywane" jako typu string.

// boolean
audio.dataset.play = true; // przypisanie wartości - zapis
audio.dataset.play = false;
const is_play = (audio.dataset.play === 'true'); // odczyt

// integer
let zmienna = (10 * 3) - 2;
audio.dataset.playlistIndex = 3; // zapis
audio.dataset.playlistIndex = zmienna;
const playlist_index = parseInt(audio.dataset.playlistIndex) || 0; // odczyt

... itd

 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

+1 głos
1 odpowiedź 306 wizyt
pytanie zadane 18 sierpnia 2021 w Nasze projekty przez qax Dyskutant (8,060 p.)
+2 głosów
3 odpowiedzi 996 wizyt
pytanie zadane 31 grudnia 2015 w Nasze projekty przez Tricker Bywalec (2,630 p.)
0 głosów
2 odpowiedzi 298 wizyt
pytanie zadane 12 maja 2016 w HTML i CSS przez Nicolaus Dyskutant (9,740 p.)

92,579 zapytań

141,432 odpowiedzi

319,662 komentarzy

61,964 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...