audio_player-1.0.x-dev/js/single-audio/skin-one.js

js/single-audio/skin-one.js
(function ($, Drupal, drupalSettings) {
  'use strict';

  // --- Common Helper Functions (moved outside the loop) ---

  /**
   * Formats time from seconds to MM:SS format.
   * @param {number} seconds - The time in seconds.
   * @returns {string} Formatted time string (MM:SS).
   */
  function formatTime(seconds) {
    const minutes = Math.floor(seconds / 60);
    const secs = Math.floor(seconds % 60);
    return `${minutes}:${secs < 10 ? '0' : ''}${secs}`;
  }

  // --- Drupal Behavior ---

  Drupal.behaviors.audio_player = {
    attach: function (context, settings) {
      $(function () {
        once('audio_player', '.audio-player.skin-one', context).forEach(function (playerElement) {
          const $player = $(playerElement);

          // Get references to all necessary DOM elements
          const audioElement = $player.find('.audio-player-element').get(0); // Get native DOM element
          const $playPauseBtn = $player.find('.audio-player-play-pause-button');
          const $playIcon = $player.find('.audio-player-play-icon');
          const $pauseIcon = $player.find('.audio-player-pause-icon');
          const $rewindBtn = $player.find('.audio-player-rewind-button');
          const $forwardBtn = $player.find('.audio-player-forward-button');
          const $volumeIconBtn = $player.find('.audio-player-volume-icon-button');
          const $volumeHighIcon = $player.find('.audio-player-volume-high-icon');
          const $volumeMuteIcon = $player.find('.audio-player-volume-mute-icon');
          const $volumeSlider = $player.find('.audio-player-volume-slider');
          const $progressBarContainer = $player.find('.audio-player-progress-bar-container');
          const $progressBar = $player.find('.audio-player-progress-bar');
          const $bufferedBar = $player.find('.audio-player-buffered-bar');
          const $currentTimeSpan = $player.find('.audio-player-current-time');
          const $durationSpan = $player.find('.audio-player-duration');
          const $songNameDisplay = $player.find('.audio-player-song-name');

          // State variables for playback and mute status
          let isPlaying = 0;
          let prevVolume = 1; // Stores volume before muting (when setting slider to 0)
          let isDraggingProgressBar = 0; // Flag to track if the progress bar is being dragged
          let isDraggingVolume = 0; // Flag to track if the volume slider is being dragged

          $durationSpan.text(formatTime(audioElement.duration));

          /**
           * Updates the buffered bar's width based on audio buffering progress.
           */
          function updateBufferedBar() {
            const duration = audioElement.duration;
            if (!isNaN(duration) && duration > 0) {
              if (audioElement.buffered.length > 0) {
                const bufferedEnd = audioElement.buffered.end(audioElement.buffered.length - 1);
                const bufferedPercent = (bufferedEnd / duration) * 100;
                $bufferedBar.css('width', bufferedPercent + '%');
              } else {
                $bufferedBar.css('width', '0%');
              }
            } else {
              $bufferedBar.css('width', '0%');
            }
          }

          /**
           * Toggles between play and pause states for the audioElement.
           */
          function togglePlayPause() {
            if (isPlaying) {
              audioElement.pause();
              $playIcon.show();
              $pauseIcon.hide();
              $playPauseBtn.removeClass('audio-player-play-pause-button-active');
            } else {
              audioElement.play();
              $playIcon.hide();
              $pauseIcon.show();
              $playPauseBtn.addClass('audio-player-play-pause-button-active');
            }
            isPlaying = !isPlaying;
          }

          /**
           * Updates audio current time and progress bar based on mouse position.
           * @param {Event} e - The mouse event.
           */
          function updateProgressBar(e) {
            const rect = $progressBarContainer[0].getBoundingClientRect();
            const clickX = e.clientX - rect.left;
            const containerWidth = rect.width;

            const newProgress = (clickX / containerWidth) * 100;
            $progressBar.css('width', newProgress + '%');

            const newTime = (clickX / containerWidth) * audioElement.duration;
            if (!isNaN(audioElement.duration)) {
              audioElement.currentTime = newTime;
            }
          }

          /**
           * Updates the volume of the audio and the volume slider's visual fill.
           * @param {Event} e - The mouse event.
           */
          function updateVolume(e) {
            const rect = $volumeSlider[0].getBoundingClientRect();
            const clickX = e.clientX - rect.left;
            const sliderWidth = rect.width;
            let newVolume = (clickX / sliderWidth);

            newVolume = Math.max(0, Math.min(1, newVolume));

            audioElement.volume = newVolume;
            $volumeSlider.val(newVolume);
            $volumeSlider[0].style.setProperty('--value', (newVolume * 100) + '%');
          }

          /**
           * Updates the volume icon based on the current audio volume (muted/unmuted).
           */
          function updateVolumeIcon() {
            if (audioElement.volume === 0 || audioElement.muted) {
              $volumeHighIcon.hide();
              $volumeMuteIcon.show();
            } else {
              $volumeHighIcon.show();
              $volumeMuteIcon.hide();
            }
          }

          // --- Event Listeners ---

          $playPauseBtn.on('click', togglePlayPause);

          $(audioElement).on('timeupdate', () => {
            if (!isDraggingProgressBar && !isNaN(audioElement.duration) && audioElement.duration > 0) {
              const progress = (audioElement.currentTime / audioElement.duration) * 100;
              $progressBar.css('width', progress + '%');
            }
            $currentTimeSpan.text(formatTime(audioElement.currentTime));
            updateBufferedBar();
          });

          $(audioElement).on('progress', updateBufferedBar);

          // Function to update metadata once loaded
          const updateMetadata = () => {
            $durationSpan.text(formatTime(audioElement.duration));
            const audioSrc = audioElement.src;
            const fileName = audioSrc.substring(audioSrc.lastIndexOf('/') + 1);
            $songNameDisplay.text(decodeURIComponent(fileName.replace(/\.[^/.] + $ / , "")));
            $volumeSlider.val(audioElement.volume);
            updateBufferedBar();
          };

          // Trigger when the page loads or when audio metadata is loaded
          $(audioElement).on('loadedmetadata', updateMetadata);  // When audio metadata is loaded

          updateMetadata();

          $(audioElement).on('loadeddata', updateBufferedBar);

          $progressBarContainer.on('mousedown', (e) => {
            isDraggingProgressBar = 1;
            if (isPlaying) {
              audioElement.pause();
            }
            updateProgressBar(e);
            e.preventDefault();
          });

          $(document).on('mousemove', (e) => {
            if (isDraggingProgressBar) {
              updateProgressBar(e);
            }
          });

          $(document).on('mouseup', () => {
            if (isDraggingProgressBar) {
              isDraggingProgressBar = 0;
              if (isPlaying) {
                audioElement.play();
              }
              if (isPlaying) {
                $playIcon.hide();
                $pauseIcon.show();
              } else {
                $playIcon.show();
                $pauseIcon.hide();
              }
            }
          });

          $rewindBtn.on('click', () => {
            audioElement.currentTime = Math.max(0, audioElement.currentTime - 10);
          });

          $forwardBtn.on('click', () => {
            audioElement.currentTime = Math.min(audioElement.duration, audioElement.currentTime + 10);
          });

          $volumeSlider.on('mousedown', (e) => {
            isDraggingVolume = 1;
            updateVolume(e);
            e.preventDefault();
          });

          $(document).on('mousemove', (e) => {
            if (isDraggingVolume) {
              updateVolume(e);
            }
          });

          $(document).on('mouseup', () => {
            if (isDraggingVolume) {
              isDraggingVolume = 0;
              if (audioElement.volume === 0 && prevVolume === 0) {
                prevVolume = 1;
              } else if (audioElement.volume > 0) {
                prevVolume = audioElement.volume;
              }
            }
          });

          $(audioElement).on('volumechange', () => {
            if (!isDraggingVolume) {
              $volumeSlider.val(audioElement.volume);
              $volumeSlider[0].style.setProperty('--value', (audioElement.volume * 100) + '%');
            }
            updateVolumeIcon();
          });

          $volumeIconBtn.on('click', () => {
            if (audioElement.volume === 0) {
              audioElement.volume = prevVolume;
            } else {
              prevVolume = audioElement.volume;
              audioElement.volume = 0;
            }
            $volumeSlider.val(audioElement.volume);
            $volumeSlider[0].style.setProperty('--value', (audioElement.volume * 100) + '%');
            updateVolumeIcon();
          });

          $(audioElement).on('ended', () => {
            isPlaying = 0;
            $playIcon.show();
            $pauseIcon.hide();
            $playPauseBtn.removeClass('audio-player-play-pause-button-active');
            $progressBar.css('width', '0%');
            $bufferedBar.css('width', '0%');
            $currentTimeSpan.text('0:00');
            audioElement.currentTime = 0;
            $volumeSlider[0].style.setProperty('--value', (audioElement.volume * 100) + '%');
            updateVolumeIcon();
          });

          // Set initial song name from the audio source URL
          const audioSrc = audioElement.src;
          const fileName = audioSrc.substring(audioSrc.lastIndexOf('/') + 1);
          $songNameDisplay.text(decodeURIComponent(fileName));

          // Initial calls to set visual states
          updateBufferedBar();
          $volumeSlider[0].style.setProperty('--value', (audioElement.volume * 100) + '%');
          updateVolumeIcon();
        });
      });
    }
  };
})(jQuery, Drupal, drupalSettings);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc