From 85718cac3059ce707556757a3bdb83f2990ef8d4 Mon Sep 17 00:00:00 2001 From: Dan Pastori Date: Sat, 14 Jul 2018 18:02:30 -0700 Subject: [PATCH] Fixes the issue where getting songs in a playlist returns the wrong songs. References #265 --- dist/amplitude.js | 3 ++- dist/amplitude.js.map | 2 +- dist/amplitude.min.js | 2 +- src/index.js | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/dist/amplitude.js b/dist/amplitude.js index 76cc22dd..92e8d0f9 100644 --- a/dist/amplitude.js +++ b/dist/amplitude.js @@ -6105,7 +6105,8 @@ var Amplitude = function () { var songsArray = []; for (var i = 0; i < _config2.default.playlists[playlist].length; i++) { - songsArray.push(_config2.default.songs[i]); + var songIndex = _config2.default.playlists[playlist][i]; + songsArray.push(_config2.default.songs[songIndex]); } return songsArray; diff --git a/dist/amplitude.js.map b/dist/amplitude.js.map index 1927c7d3..d4860922 100644 --- a/dist/amplitude.js.map +++ b/dist/amplitude.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap c7a95984b8c01460a8bc","webpack:///./src/config.js","webpack:///./src/core/helpers.js","webpack:///./src/visual/visual.js","webpack:///./src/core/core.js","webpack:///./src/events/events.js","webpack:///./src/events/helpers.js","webpack:///./src/init/init.js","webpack:///./src/events/handlers.js","webpack:///./src/index.js","webpack:///./src/soundcloud/soundcloud.js","webpack:///./src/visual/helpers.js"],"names":["module","exports","version","active_song","Audio","active_metadata","active_album","active_index","active_playlist","autoplay","playback_speed","callbacks","songs","playlists","start_song","shuffled_playlists","starting_playlist","starting_playlist_song","shuffled_statuses","shuffled_active_indexes","repeat_statuses","repeat","repeat_song","shuffle_list","shuffle_on","shuffle_active_index","default_album_art","debug","volume","pre_mute_volume","volume_increment","volume_decrement","soundcloud_client","soundcloud_use_art","soundcloud_song_count","soundcloud_songs_ready","is_touch_moving","buffered","bindings","continue_next","AmplitudeHelpers","resetConfig","handle_song_elements","writeDebugMessage","message","console","log","runCallback","callbackName","callbackFunction","error","changeSong","songIndex","song","stop","setPlayPauseButtonsToPause","resetSongSliders","resetSongPlayedProgressBars","resetTimes","checkNewAlbum","setNewSong","displaySongMetadata","setActiveContainer","syncSongDuration","checkNewSong","newAlbum","checkNewPlaylist","playlist","index","src","url","album","shuffleSongs","shuffleTemp","Array","length","i","original_index","randNum","Math","floor","random","shuffleSwap","shufflePlaylistSongs","shuffleList","original","temp","setActivePlaylist","isURL","pattern","test","isInt","int","isNaN","parseInt","Number","AmplitudeVisualSync","syncCurrentTime","currentTime","completionPercentage","syncCurrentHours","hours","syncCurrentMinutes","minutes","syncCurrentSeconds","seconds","syncMainSliderLocation","syncPlaylistSliderLocation","syncSongSliderLocation","syncSongPlayedProgressBar","resetCurrentHours","resetCurrentMinutes","resetCurrentSeconds","resetCurrentTime","songSliders","document","getElementsByClassName","value","resetSongBufferedProgressBars","songBufferedProgressBars","songPlayedProgressBars","songContainers","classList","remove","querySelectorAll","hasAttribute","add","imageMetaDataKeys","ignoredKeys","songInfoElements","info","getAttribute","main","undefined","indexOf","setAttribute","innerHTML","setFirstSongInPlaylist","elementPlaylist","syncPlaybackSpeed","playbackSpeedClasses","syncBufferedProgressBars","parseFloat","syncVolumeSliders","amplitudeVolumeSliders","playPauseElements","setElementPause","syncMainPlayPause","state","paused","setElementPlay","syncPlaylistPlayPause","playlistPlayPauseElements","syncSongPlayPause","songPlayPauseElements","syncRepeat","repeatClasses","syncRepeatPlaylist","repeatButtons","syncRepeatSong","repeatSongClasses","syncMute","muteClasses","syncShuffle","shuffleButtons","syncPlaylistShuffle","location","mainSongSliders","playlistSongSliders","syncVolumeSliderLocation","volumeSliders","songDuration","syncDurationHours","syncDurationMinutes","syncDurationSeconds","syncDurationTime","syncCountDownTime","syncSongsMetaData","AmplitudeCore","play","live","reconnectStream","navigator","userAgent","playbackRate","pause","disconnectStream","setVolume","volumeLevel","setSongLocation","songPercentage","duration","song_percentage","skipToLocation","addEventListener","once","load","playNow","playSongAtIndex","playPlaylistSongAtIndex","setPlaybackSpeed","playbackSpeed","AmplitudeEvents","initializeEvents","bindTimeUpdate","bindKeyDownEventHandlers","bindSongEnded","bindProgress","bindPlay","bindPause","bindPlayPause","bindStop","bindMute","bindVolumeUp","bindVolumeDown","bindSongSlider","bindVolumeSlider","bindNext","bindPrev","bindShuffle","bindRepeat","bindPlaybackSpeed","bindSkipTo","removeEventListener","updateTime","keydown","songEnded","progess","progress","play_classes","pause_classes","play_pause_classes","playPause","stop_classes","mute_classes","mute","volume_up_classes","volumeUp","volume_down_classes","volumeDown","ua","window","msie","song_sliders","match","songSlider","volume_sliders","volumeSlider","next_classes","next","prev_classes","prev","shuffle_classes","shuffle","repeat_classes","playback_speed_classes","skipToClasses","skipTo","AmplitudeEventsHelpers","computeCurrentTimes","currentSeconds","currentMinutes","currentHours","computeSongDuration","songDurationSeconds","songDurationMinutes","songDurationHours","computeSongCompletionPercentage","speed","setRepeat","setRepeatSong","setMainPlayPause","setPlaylistPlayPause","setSongPlayPause","setShuffle","setNext","nextIndex","endOfList","setNextPlaylist","shuffledPlaylistActiveSongIndex","playlistActiveSongIndex","setPrev","prevIndex","setPrevPlaylist","runKeyEvent","key","AmplitudesEventHelpers","AmplitudeEvenstHelpers","AmplitudeInitializer","initialize","userConfig","ready","countPlaylists","initializeDefaultLiveSettings","checkValidSongsInPlaylists","initializePlaylistShuffleStatuses","initializePlaylistsRepeatStatuses","initializePlaylistShuffleLists","initializePlaylistShuffleIndexes","initializeFirstSongInPlaylistMetaData","tempUserConfig","loadSoundCloud","setConfig","rebindDisplay","preload","size","hasOwnProperty","bufferedEnd","end","songCompletionPercentage","event","which","playButtonSongIndex","playButtonPlaylistIndex","pauseButtonSongIndex","pauseButtonPlaylistIndex","muted","locationPercentage","isFinite","repeatSong","Amplitude","init","bindNewElements","getActivePlaylist","getPlaybackSpeed","getRepeat","getShuffle","getShufflePlaylist","setShufflePlaylist","playlistKey","getDefaultAlbumArt","setDefaultAlbumArt","getSongPlayedPercentage","setSongPlayedPercentage","percentage","setDebug","getActiveSongMetadata","getSongByIndex","getSongAtPlaylistIndex","addSong","push","addSongToPlaylist","removeSong","splice","removeSongFromPlaylist","getAudio","getSongs","getSongsInPlaylist","songsArray","getSongsState","getSongsStatePlaylist","shuffled_status","getActiveIndex","getActiveIndexState","getVersion","getBuffered","audio","AmplitudeSoundcloud","head","getElementsByTagName","script","createElement","type","onreadystatechange","initSoundcloud","onload","appendChild","SC","client_id","getStreamableURLs","soundcloud_regex","resolveStreamable","get","sound","streamable","stream_url","cover_art_url","artwork_url","soundcloud_data","name","artist","AmplitudeVisualSyncHelpers","hourSelectors","join","currentHourSelectors","minuteSelectors","currentMinuteSelectors","l","secondSelectors","currentSecondSelectors","timeSelectors","currentTimeSelectors","timeText","songPlayedPercentage","syncMainSongPlayedProgressBars","syncPlaylistSongPlayedProgressBars","syncIndividualSongPlayedProgressBars","max","element","durationHourSelectors","durationMinuteSelectors","durationSecondSelectors","durationTime","durationTimeSelectors","durationText","timeRemaining","totalCurrentSeconds","totalDurationSeconds","timeRemainingTotalSeconds","remainingHours","remainingMinutes","remainingSeconds","timeRemainingSelectors"],"mappings":"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","file":"amplitude.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"Amplitude\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Amplitude\"] = factory();\n\telse\n\t\troot[\"Amplitude\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 8);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap c7a95984b8c01460a8bc","/**\n * These variables make Amplitude run. The config is the most important\n * containing active settings and parameters.\n *\n * The config JSON is the global settings for ALL of Amplitude functions.\n * This is global and contains all of the user preferences. The default\n * settings are set, and the user overwrites them when they initialize\n * Amplitude.\n *\n * @module config\n * @type {object}\n * @property {string} \tconfig.version \t\t\t\t- The current version of AmplitudeJS.\n * @property {object} \tconfig.active_song \t\t \t\t\t\t\t-\tHandles all of the audio.\n * @property {object} \tconfig.active_metadata\t\t\t\t\t- Contains the active metadata for the song.\n * @property {string} \tconfig.active_album\t\t\t\t\t\t\t- Holds the active album name. Used to check and see if the album changed and run the album changed callback.\n * @property {number} \tconfig.active_index\t\t\t\t\t\t\t- Contains the index of the actively playing song.\n * @property {string} \tconfig.active_playlist\t\t\t\t\t- Contains the key to the active playlist index.\n * @property {boolean}\tconfig.autoplay\t\t\t\t\t\t\t\t\t- Set to true to autoplay the song\n * @property {number} \tconfig.playback_speed\t\t\t\t\t\t- Sets the initial playback speed of the song. The values for this can be 1.0, 1.5, 2.0\n * @property {object} \tconfig.callbacks\t\t\t\t\t\t\t\t- The user can pass a JSON object with a key => value store of callbacks to be run at certain events.\n * @property {array} \t\tconfig.songs\t\t\t\t\t\t\t\t\t\t- Contains all of the songs the user has passed to Amplitude to use.\n * @property {object} \tconfig.playlists\t\t\t\t\t\t\t\t- Contains all of the playlists the user created.\n * @property {object} \tconfig.start_song \t\t\t\t\t\t\t- The index of the song that AmplitudeJS should start with.\n * @property {object} \tconfig.shuffled_playlists\t\t\t\t- Will contain shuffled playlists.\n * @property {string} \tconfig.starting_playlist \t\t\t\t- The starting playlist the player will intiialize to.\n * @property {string} \tconfig.starting_playlist_song \t- The index of the song in the playlist that should be started.\n * @property {object} \tconfig.shuffled_statuses \t\t\t\t- Contains whether the current playlist is in shuffle mode or not.\n * @property {object} \tconfig.repeat_statuses \t\t\t\t\t- Contains whether the playlist is in repeat mode or not.\n * @property {object} \tconfig.shuffled_active_indexes\t- Contains the active index in a shuffled playlist.\n * @property {boolean} \tconfig.repeat \t\t\t\t\t\t\t\t\t- When repeat is on, when the song ends the song will replay itself.\n * @property {object} \tconfig.shuffle_list\t\t\t\t\t\t\t- When shuffled, gets populated with the songs the user provided in a random order.\n * @property {boolean} \tconfig.shuffle_on\t\t\t\t\t\t\t\t- When on, gets set to true so when traversing through songs, AmplitudeJS knows whether or not to use the songs object or the shuffle_list\n * @property {number} \tconfig.shuffle_active_index \t\t- When shuffled, this index is used to let AmplitudeJS know where it's at when traversing.\n * @property {string}\t\tconfig.default_album_art \t\t\t\t- The user can set default album art to be displayed if the song they set doesn't contain album art.\n * @property {boolean} \tconfig.debug\t\t\t\t\t\t\t\t\t\t- When set to true, AmplitudeJS will print to the console any errors providing helpful feedback to the user.\n * @property {number} \tconfig.volume \t\t\t\t\t\t\t\t\t- The user can set the initial volume to a number between 0 and 1 over-riding the default of .5\n * @property {number} \tconfig.pre_mute_volume \t\t\t\t\t- This is set on mute so that when a user un-mutes AmplitudeJS knows what to restore the volume to.\n * @property {number}\t\tconfig.volume_increment \t\t\t\t- The default values are an integer between 1 and 100 for how much the volume should increase when the user presses the volume up button.\n * @property {number}\t\tconfig.volume_decrement \t\t\t\t- The default values are an integer between 1 and 100 for how much the volume should decrease when the user presses the volume down button.\n * @property {string} \tconfig.soundcloud_client \t\t\t\t- When using SoundCloud, the user will have to provide their API Client ID\n * @property {boolean} \tconfig.soundcloud_use_art \t\t\t- The user can set this to true and AmplitudeJS will use the album art for the song returned from the Soundcloud API\n * @property {number} \tconfig.soundcloud_song_count \t\t- Used on config to count how many songs are from Soundcloud and compare it to how many are ready for when to move to the rest of the configuration\n * @property {number} \tconfig.soundcloud_songs_ready \t- Used on config to count how many songs are ready so when we get all of the data from the SoundCloud API that we need this should match the SoundCloud song count meaning we can move to the rest of the config.\n * @property {integer}\tconfig.is_touch_moving \t\t\t\t\t- Flag for if the user is moving the screen.\n * @property {boolean}\tconfig.buffered\t\t\t\t\t\t\t\t\t- How much of the song is buffered.\n * @property {object} \tconfig.bindings\t\t\t\t\t\t\t\t\t- Array of bindings to certain key events.\n * @property {boolean} \tconfig.continue_next \t\t\t\t\t\t- Determines when a song ends, we should continue to the next song.\n */\nmodule.exports = {\n\tversion: '3.3.0',\n\n\tactive_song: new Audio(),\n\n\tactive_metadata: {},\n\n\tactive_album: '',\n\n\tactive_index: 0,\n\n\tactive_playlist: '',\n\n\tautoplay: false,\n\n\tplayback_speed: 1.0,\n\n\tcallbacks: {},\n\n\tsongs: [],\n\n\tplaylists: {},\n\n\tstart_song: '',\n\n\tshuffled_playlists: {},\n\n\tstarting_playlist: '',\n\n\tstarting_playlist_song: '',\n\n\tshuffled_statuses: {},\n\n\tshuffled_active_indexes: {},\n\n\trepeat_statuses: {},\n\n\trepeat: false,\n\n\trepeat_song: false,\n\n\tshuffle_list: {},\n\n\tshuffle_on: false,\n\n\tshuffle_active_index: 0,\n\n\tdefault_album_art: '',\n\n\tdebug: false,\n\n\tvolume: .5,\n\n\tpre_mute_volume: .5,\n\n\tvolume_increment: 5,\n\n\tvolume_decrement: 5,\n\n\tsoundcloud_client: '',\n\n\tsoundcloud_use_art: false,\n\n\tsoundcloud_song_count: 0,\n\n\tsoundcloud_songs_ready: 0,\n\n\tis_touch_moving: false,\n\n\tbuffered: 0,\n\n\tbindings: {},\n\n\tcontinue_next: true\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/config.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * AmplitudeJS Core Module\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * AmplitudeJS Visual Sync\n * @module visual/AmplitudeVisualSync\n*/\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * For the sake of code clarity, these functions perform helper tasks\n * assisting the logical functions with what they need such as setting\n * the proper song index after an event has occured.\n *\n * @module core/AmplitudeHelpers\n */\nlet AmplitudeHelpers = (function () {\n\t/**\n\t * Resets the config to the default state. This is called on initialize\n\t * to ensure the user's config is what matters.\n\t *\n\t * Public Accessor: AmplitudeHelpers.resetConfig()\n\t *\n\t * @access public\n\t */\n\tfunction resetConfig(){\n\t\tconfig.active_song \t\t\t\t\t\t\t= new Audio();\n\t\tconfig.active_metadata \t\t\t\t\t= {};\n\t\tconfig.active_album \t\t\t\t\t\t= '';\n\t\tconfig.active_index \t\t\t\t\t\t= 0;\n\t\tconfig.active_playlist \t\t\t\t\t= '';\n\t\tconfig.active_playlist \t\t\t\t\t= '';\n\t\tconfig.autoplay \t\t\t\t\t\t\t\t= false;\n\t\tconfig.playback_speed \t\t\t\t\t= 1.0;\n\t\tconfig.callbacks \t\t\t\t\t\t\t\t= {};\n\t\tconfig.songs \t\t\t\t\t\t\t\t\t\t= [];\n\t\tconfig.playlists \t\t\t\t\t\t\t\t= {};\n\t\tconfig.start_song \t\t\t\t\t\t\t= '';\n\t\tconfig.shuffled_playlists \t\t\t= {};\n\t\tconfig.starting_playlist \t\t\t\t= '';\n\t\tconfig.starting_playlist_song \t= '';\n\t\tconfig.shuffled_statuses \t\t\t\t= {};\n\t\tconfig.repeat \t\t\t\t\t\t\t\t\t= false;\n\t\tconfig.shuffle_list \t\t\t\t\t\t= {};\n\t\tconfig.shuffle_on \t\t\t\t\t\t\t= false;\n\t\tconfig.shuffle_active_index \t\t= 0;\n\t\tconfig.default_album_art \t\t\t\t= '';\n\t\tconfig.debug \t\t\t\t\t\t\t\t\t\t= false;\n\t\tconfig.handle_song_elements \t\t= true;\n\t\tconfig.volume \t\t\t\t\t\t\t\t\t= .5;\n\t\tconfig.pre_mute_volume \t\t\t\t\t= .5;\n\t\tconfig.volume_increment \t\t\t\t= 5;\n\t\tconfig.volume_decrement \t\t\t\t= 5;\n\t\tconfig.soundcloud_client \t\t\t\t= '';\n\t\tconfig.soundcloud_use_art \t\t\t= false;\n\t\tconfig.soundcloud_song_count \t\t= 0;\n\t\tconfig.soundcloud_songs_ready \t= 0;\n\t\tconfig.continue_next \t\t\t\t\t\t= true;\n\t}\n\n\t/**\n\t * Writes out debug message to the console if enabled.\n\t *\n\t * Public Accessor: AmplitudeHelpers.writeDebugMessage( message )\n\t *\n\t * @access public\n\t * @param {string} message - The string that gets printed to alert the user of a debugging error.\n\t */\n\tfunction writeDebugMessage( message ){\n\t\tif( config.debug ){\n\t\t\tconsole.log( message );\n\t\t}\n\t}\n\n\t/**\n\t * Runs a user defined callback method\n\t *\n\t * Public Accessor: AmplitudeHelpers.runCallback( callbackName )\n\t *\n\t * @access public\n\t * @param {string} callbackName - The name of the callback we are going to run.\n\t */\n\tfunction runCallback( callbackName ){\n\t\t/*\n\t\t\tChecks to see if a user defined a callback method for the\n\t\t\tcallback we are running.\n\t\t*/\n\t\tif( config.callbacks[callbackName] ){\n\t\t\t/*\n\t\t\t\tBuild the callback function\n\t\t\t*/\n\t\t\tlet callbackFunction = config.callbacks[ callbackName ];\n\n\t\t\t/*\n\t\t\t\tWrite a debug message stating the callback we are running\n\t\t\t*/\n\t\t\twriteDebugMessage( 'Running Callback: '+callbackName );\n\n\t\t\t/*\n\t\t\t\tRun the callback function and catch any errors\n\t\t\t*/\n try {\n callbackFunction();\n }catch( error ) {\n if( error.message == \"CANCEL EVENT\" ){\n throw error;\n }else{\n writeDebugMessage( 'Callback error: '+error.message );\n\t\t\t\t}\n }\n\t\t}\n\t}\n\n\t/**\n\t * Changes the active song in the config. This happens in multiple\n\t * scenarios: The user clicks a play button that has an index that is\n\t * different than what is currently playing, the song ends and the next\n\t * song begins, etc.\n\t *\n\t * Public Accessor: AmplitudeHelpers.changeSong( songIndex )\n\t *\n\t * @access public\n\t * @param {number} songIndex - The song index we are changing to\n\t *\n\t */\n\tfunction changeSong( songIndex ){\n\t\t/*\n\t\t\tGrab the song at the index defined by the user.\n\t\t*/\n\t\tlet song = config.songs[ songIndex ];\n\n\t\t/*\n\t\t\tStops the currently playing song so we can adjust\n\t\t\twhat we need.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/**\n\t\t * @todo: Stop Visualization\n\t\t */\n\n\t\t/*\n\t\t\tSet all play buttons to pause while we change\n\t\t\tthe song.\n\t\t*/\n\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t/*\n\t\t\tSince it is a new song, we reset the song sliders. These\n\t\t\treact to time updates and will eventually be updated but we\n\t\t\tforce update them is if there is a song slider bound to a\n\t\t\tspecific song, they won't update.\n\t\t*/\n\t\tAmplitudeVisualSync.resetSongSliders();\n\n\t\t/*\n\t\t\tResets the progress bars\n\t\t*/\n\t\tAmplitudeVisualSync.resetSongPlayedProgressBars();\n\n\t\t/*\n\t\t\tReset all the time place holders accordingly.\n\t\t*/\n\t\tAmplitudeVisualSync.resetTimes();\n\n\t\t/*\n\t\t\tRun a callback if an album is going\n\t\t\tto change.\n\t\t*/\n\t\tif( checkNewAlbum( song ) ){\n\t\t\trunCallback('album_change');\n\t\t}\n\n\t\t/*\n\t\t\tSet the new song information so we can use the\n\t\t\tactive meta data later on.\n\t\t*/\n\t\tsetNewSong( song, songIndex );\n\n\t\t/*\n\t\t\tDisplay the new visual metadata now that the config has\n\t\t\tbeen changed. This will show the new song.\n\t\t*/\n\t\tAmplitudeVisualSync.displaySongMetadata();\n\n\t\t/*\n\t\t\tSets the active container. This is a class that\n\t\t\tdesigners can use on an element that contains the current\n\t\t\tsong's controls to show it's highlighted.\n\t\t*/\n\t\tAmplitudeVisualSync.setActiveContainer();\n\n\t\t/*\n\t\t\tSets the active song's duration\n\t\t*/\n\t\tAmplitudeVisualSync.syncSongDuration();\n\n\t\t/*\n\t\t\tRun song change callback.\n\t\t*/\n\t\trunCallback('song_change');\n\t}\n\n\t/**\n\t * Checks to see if the new song to be played is different than the song\n\t * that is currently playing. To be true, the user would have selected\n\t * play on a new song with a new index. To be false, the user would have\n\t * clicked play/pause on the song that was playing.\n\t *\n\t * Public Accessor: AmplitudeHelpers.checkNewSong( songIndex )\n\t *\n\t * @access public\n\t * @param {number} songIndex - The index of the new song to be played.\n\t * @returns {boolean} True if we are setting a new song, false if we are not setting a new song.\n\t */\n\tfunction checkNewSong( songIndex ){\n\t\tif( songIndex != config.active_index ){\n\t\t\treturn true;\n\t\t}else{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Checks to see if there is a new album\n\t *\n\t * Public Accessor: AmplitudeHelpers.checkNewAlbum( new Album )\n\t *\n\t * @access public\n\t * @param {string} newAlbum - Checks to see if the new song will have a new album.\n\t * @returns {boolean} True if there is a new album, false if there is not a new ablum.\n\t */\n\tfunction checkNewAlbum( newAlbum ){\n\t\tif( config.active_album != newAlbum ){\n\t\t\treturn true;\n\t\t}else{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Checks to see if there is a new playlist\n\t *\n\t * Public Accessor: AmplitudeHelpers.checkNewPlaylist( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist - The playlist passed in to check against the active playlist.\n\t * @returns {boolean} True if there is a new playlist, false if there is not a new playlist.\n\t */\n\tfunction checkNewPlaylist( playlist ){\n\t\tif( config.active_playlist != playlist ){\n\t\t\treturn true;\n\t\t}else{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Sets the new song in the config. Sets the src of the audio object,\n\t * updates the\tmetadata and sets the active album.\n\t *\n\t * @access private\n\t * @param {object} song \t- The song object of the song we are changing to.\n\t * @param {number} index \t- The index of the song in the songs object we are changing.\n\t */\n\tfunction setNewSong( song, index ){\n\t\tconfig.active_song.src \t= song.url;\n\t\tconfig.active_metadata \t= song;\n\t\tconfig.active_album \t= song.album;\n\t\tconfig.active_index \t\t= index;\n\t}\n\n\t/**\n\t * Shuffles individual songs in the config\n\t * Based off of: http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html\n\t *\n\t * Public Accessor: AmplitudeHelpers.shuffleSongs()\n\t *\n\t * @access public\n\t */\n\tfunction shuffleSongs(){\n\t\t/*\n\t\t\tBuilds a temporary array with the length of the config.\n\t\t*/\n\t\tlet shuffleTemp = new Array( config.songs.length );\n\n\t\t/*\n\t\t\tSet the temporary array equal to the songs array.\n\t\t*/\n\t\tfor( let i = 0; i < config.songs.length; i++ ){\n\t\t\tshuffleTemp[i] = config.songs[i];\n\t\t\tshuffleTemp[i].original_index = i;\n\t\t}\n\n\t\t/*\n\t\t\tIterate ove rthe songs and generate random numbers to\n\t\t\tswap the indexes of the shuffle array.\n\t\t*/\n\t\tfor( let i = config.songs.length - 1; i > 0; i-- ){\n\t\t\tlet randNum = Math.floor( ( Math.random() * config.songs.length ) + 1 );\n\t\t\tshuffleSwap( shuffleTemp, i, randNum - 1 );\n\t\t}\n\n\t\t/*\n\t\t\tSet the shuffle list to the shuffle temp.\n\t\t*/\n\t\tconfig.shuffle_list = shuffleTemp;\n\t}\n\n\t/**\n\t * Shuffle songs in a playlist\n\t *\n\t * Public Accessor: AmplitudeHelpers.shufflePlaylistSongs( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist - The playlist we are shuffling.\n\t */\n\tfunction shufflePlaylistSongs( playlist ){\n\t\t/*\n\t\t\tBuilds a temporary array with the length of the playlist songs.\n\t\t*/\n\t\tlet shuffleTemp = new Array( config.playlists[playlist].length );\n\n\t\t/*\n\t\t\tSet the temporary array equal to the playlist array.\n\t\t*/\n\t\tfor( let i = 0; i < config.playlists[playlist].length; i++ ){\n\t\t\tshuffleTemp[i] = config.songs[ config.playlists[playlist][i] ];\n\t\t\tshuffleTemp[i].original_index = config.playlists[playlist][i];\n\t\t}\n\n\t\t/*\n\t\t\tIterate ove rthe songs and generate random numbers to\n\t\t\tswap the indexes of the shuffle array.\n\t\t*/\n\t\tfor( let i = config.playlists[playlist].length - 1; i > 0; i-- ){\n\t\t\tlet randNum = Math.floor( ( Math.random() * config.playlists[playlist].length ) + 1 );\n\t\t\tshuffleSwap( shuffleTemp, i, randNum - 1 );\n\t\t}\n\n\t\t/*\n\t\t\tSet the shuffle list to the shuffle temp.\n\t\t*/\n\t\tconfig.shuffled_playlists[playlist] = shuffleTemp;\n\t}\n\n\t/**\n\t * Swaps and randomizes the song shuffle.\n\t *\n\t * @access private\n\t * @param {object} shuffleList \t- The list of songs that is going to be shuffled\n\t * @param {number} original \t\t- The original index of he song in the songs array\n\t * @param {number} random \t\t\t- The randomized index that will be the new index of the song in the shuffle array.\n\t */\n\tfunction shuffleSwap( shuffleList, original, random ){\n\t\tlet temp = shuffleList[ original ];\n\t\tshuffleList[ original ] = shuffleList[ random ];\n\t\tshuffleList[ random ] = temp;\n\t}\n\n\t/**\n\t * Sets the active playlist\n\t *\n\t * Public Accessor: AmplitudeHelpers.setActivePlaylist( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist - The string of the playlist being set to active.\n\t */\n\tfunction setActivePlaylist( playlist ){\n\t\t/*\n\t\t\tIf the active playlist is different than the playlist being set,\n\t\t\twe run the `playlist_changed` callback.\n\t\t*/\n\t\tif( config.active_playlist != playlist ){\n\t\t\trunCallback('playlist_changed');\n\t\t}\n\n\t\t/*\n\t\t\tSet the active playlist to the playlist parameter.\n\t\t*/\n\t\tconfig.active_playlist = playlist;\n\t}\n\n\t/**\n\t * Determines if the string passed in is a URL or not\n\t *\n\t * Public Accessor: AmplitudeHelpers.isURL( url )\n\t *\n\t * @access public\n\t * @param {string} url - The string we are testing to see if it's a URL.\n\t * @returns {boolean} True if the string is a url, false if it is not.\n\t */\n\tfunction isURL( url ){\n\t\t/*\n\t\t\tTest the string against the URL pattern and return if it matches\n\t\t*/\n\t\tlet pattern = /(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?/\n\n\t\treturn pattern.test( url );\n\t}\n\n\t/**\n\t * Determines if what is passed in is an integer or not.\n\t *\n\t * Public Accessor: AmplitudeHelpers.isInt( int )\n\t *\n\t * @access public\n\t * @param {string|number} int - The variable we are testing to see is an integer or not.\n\t * @returns {boolean} If the variable is an integer or not.\n\t */\n\tfunction isInt( int ){\n\t\treturn !isNaN( int ) &&\n \t\tparseInt( Number( int ) ) == int &&\n \t\t!isNaN( parseInt( int, 10 ) );\n\t}\n\n\t/*\n\t\tReturns the public functions\n\t*/\n\treturn {\n\t\tresetConfig: resetConfig,\n\t\twriteDebugMessage: writeDebugMessage,\n\t\trunCallback: runCallback,\n\t\tchangeSong: changeSong,\n\t\tcheckNewSong: checkNewSong,\n\t\tcheckNewAlbum: checkNewAlbum,\n\t\tcheckNewPlaylist: checkNewPlaylist,\n\t\tshuffleSongs: shuffleSongs,\n\t\tshufflePlaylistSongs: shufflePlaylistSongs,\n\t\tsetActivePlaylist: setActivePlaylist,\n\t\tisURL: isURL,\n\t\tisInt: isInt\n\t}\n})();\n\nexport default AmplitudeHelpers\n\n\n\n// WEBPACK FOOTER //\n// ./src/core/helpers.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the Amplitude Visual Sync Helpers to keep the display in sync\n * @module visual/AmplitudeVisualSyncHelpers\n */\nimport AmplitudeVisualSyncHelpers from './helpers.js';\n\n\n/**\n * Helps with the syncing of the display data\n *\n * @module visual/AmplitudeVisualSync\n */\nlet AmplitudeVisualSync = (function() {\n\t/**\n\t * Visually displays the current time on the screen. This is called on\n\t * time update for the current song.\n\t *\n\t * @access public\n\t * @param {object} currentTime \t\t\t\t\t- An object containing the current time for the song in seconds, minutes, and hours.\n\t * @param {float} completionPercentage\t- The percent of the way through the song the user is at.\n\t */\n\tfunction syncCurrentTime( currentTime, completionPercentage ){\n\t\t/*\n\t\t\tSet current hour display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentHours( currentTime.hours );\n\n\t\t/*\n\t\t\tSet current minute display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentMinutes( currentTime.minutes );\n\n\t\t/*\n\t\t\tSet current second display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentSeconds( currentTime.seconds );\n\n\t\t/*\n\t\t\tSet current time display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentTime( currentTime );\n\n\t\t/*\n\t\t\tSet all song sliders to be to the current percentage\n\t\t\tof the song played.\n\t\t*/\n\t\tsyncMainSliderLocation( completionPercentage );\n\t\tsyncPlaylistSliderLocation( config.active_playlist, completionPercentage );\n\t\tsyncSongSliderLocation( config.active_playlist, config.active_index, completionPercentage );\n\n\t\tAmplitudeVisualSyncHelpers.syncSongPlayedProgressBar( completionPercentage );\n\t}\n\n\t/**\n\t * Visually sync all of the times to the initial time of 0. This is so\n\t * we can keep all the players in sync\n\t *\n\t * @access public\n\t */\n\tfunction resetTimes(){\n\t\tAmplitudeVisualSyncHelpers.resetCurrentHours();\n\t\tAmplitudeVisualSyncHelpers.resetCurrentMinutes();\n\t\tAmplitudeVisualSyncHelpers.resetCurrentSeconds();\n\t\tAmplitudeVisualSyncHelpers.resetCurrentTime();\n\t}\n\n\t/**\n\t * Visually syncs the song sliders back to 0. This usually happens when\n\t * a song has changed, we ensure that all song sliders get reset.\n\t *\n\t * @access public\n\t */\n\tfunction resetSongSliders(){\n\t\tlet songSliders = document.getElementsByClassName(\"amplitude-song-slider\");\n\n\t\t/*\n\t\t\tIterate over all of the song sliders and set them to\n\t\t\t0 essentially resetting them.\n\t\t*/\n\t\tfor( let i = 0; i < songSliders.length; i++ ){\n\t\t\tsongSliders[i].value = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the song buffered progress bars to 0\n\t *\n\t * @access public\n\t */\n\tfunction resetSongBufferedProgressBars(){\n\t\t/*\n\t\t\tGets all of the song buffered progress bars.\n\t\t*/\n\t\tlet songBufferedProgressBars = document.getElementsByClassName(\"amplitude-buffered-progress\");\n\n\t\t/*\n\t\t\tIterate over all of the song buffered progress bar and\n\t\t\tset them to 0 which is like re-setting them.\n\t\t*/\n\t\tfor( let i = 0; i < songBufferedProgressBars.length; i++ ){\n\t\t\tsongBufferedProgressBars[i].value = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the song played progress bars to 0\n\t *\n\t * @access public\n\t */\n\tfunction resetSongPlayedProgressBars(){\n\t\tlet songPlayedProgressBars = document.getElementsByClassName(\"amplitude-song-played-progress\");\n\n\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\tsongPlayedProgressBars[i].value = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Applies the class 'amplitude-active-song-container' to the element\n\t * containing visual information regarding the active song.\n\t *\n\t * @access public\n\t */\n\tfunction setActiveContainer(){\n\t\tlet songContainers = document.getElementsByClassName('amplitude-song-container');\n\n\t\t/*\n\t\t\tRemoves all of the active song containrs.\n\t\t*/\n\t\tfor( let i = 0; i < songContainers.length; i++ ){\n\t\t\tsongContainers[i].classList.remove('amplitude-active-song-container');\n\t\t}\n\n\t\t/*\n\t\t\tFinds the active index and adds the active song container to the element\n\t\t\tthat represents the song at the index.\n\t\t*/\n\t\tif( config.active_playlist == '' || config.active_playlist == null ){\n\t\t\tif( document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"]') ){\n\t\t\t\tlet songContainers = document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songContainers.length; i++ ){\n\t\t\t\t\tif( !songContainers[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tsongContainers[i].classList.add('amplitude-active-song-container');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tif( document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"][amplitude-playlist=\"'+config.active_playlist+'\"]') ){\n\t\t\t\tlet songContainers = document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"][amplitude-playlist=\"'+config.active_playlist+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songContainers.length; i++ ){\n\t\t\t\t\tsongContainers[i].classList.add('amplitude-active-song-container');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Displays the active song's metadata. This is called after a song has\n\t * been changed. This method takes the active song and displays the\n\t * metadata. So once the new active song is set, we update all of the\n\t * screen elements.\n\t *\n\t * @access public\n\t */\n\tfunction displaySongMetadata(){\n\t\t/*\n\t\t\tDefine the image meta data keys. These are managed separately\n\t\t\tsince we aren't actually changing the inner HTML of these elements.\n\t\t*/\n\t\tlet imageMetaDataKeys \t= ['cover_art_url', 'station_art_url', 'podcast_episode_cover_art_url'];\n\n\t\t/*\n\t\t\tThese are the ignored keys that we won't be worrying about displaying.\n\t\t\tEvery other key in the song object can be displayed.\n\t\t*/\n\t\tlet ignoredKeys \t\t= ['url', 'live'];\n\n\t\t/*\n\t\t\tGet all of the song info elements\n\t\t*/\n\t\tlet songInfoElements = document.querySelectorAll('[amplitude-song-info]');\n\n\t\t/*\n\t\t\tIterate over all of the song info elements. We will either\n\t\t\tset these to the new values, or clear them if the active song\n\t\t\tdoesn't have the info set.\n\t\t*/\n\t\tfor( let i = 0; i < songInfoElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tGet the info so we can check if the active meta data has the\n\t\t\t\tkey.\n\t\t\t*/\n\t\t\tlet info = songInfoElements[i].getAttribute('amplitude-song-info');\n\n\t\t\t/*\n\t\t\t\tGet the song info element playlist.\n\t\t\t*/\n\t\t\tlet playlist = songInfoElements[i].getAttribute('amplitude-playlist');\n\n\t\t\t/*\n\t\t\t\tGet the main song info flag.\n\t\t\t*/\n\t\t\tlet main = songInfoElements[i].getAttribute('amplitude-main-song-info');\n\n\t\t\t/*\n\t\t\t\tIf the playlists match or the element is a main element, then\n\t\t\t\twe set the song info.\n\t\t\t*/\n\t\t\tif( config.active_playlist == playlist || main == 'true' ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active metadata has the key, then we set it,\n\t\t\t\t\totherwise we clear it. If it's an image element then\n\t\t\t\t\twe default it to the default info if needed.\n\t\t\t\t*/\n\t\t\t\tif( config.active_metadata[info] != undefined ){\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', config.active_metadata[info]);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = config.active_metadata[info];\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tWe look for the default album art because\n\t\t\t\t\t\tthe actual key didn't exist. If the default album\n\t\t\t\t\t\tart doesn't exist then we set the src attribute\n\t\t\t\t\t\tto null.\n\t\t\t\t\t*/\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tif( config.default_album_art != '' ){\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', config.default_album_art);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', '');\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = '';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n * Sets the first song in the playlist. This is used to fill in the meta\n\t * data in the playlist\n\t *\n\t * @param {object} song \t\t\t- The song we are setting to be the first song in the playlist\n\t * @param {string} playlist \t- Key of the playlist we are setting the first song in\n\t */\n\tfunction setFirstSongInPlaylist( song, playlist ){\n\t\t/*\n\t\t\tDefine the image meta data keys. These are managed separately\n\t\t\tsince we aren't actually changing the inner HTML of these elements.\n\t\t*/\n\t\tlet imageMetaDataKeys \t= ['cover_art_url', 'station_art_url', 'podcast_episode_cover_art_url'];\n\n\t\t/*\n\t\t\tThese are the ignored keys that we won't be worrying about displaying.\n\t\t\tEvery other key in the song object can be displayed.\n\t\t*/\n\t\tlet ignoredKeys \t\t= ['url', 'live'];\n\n\t\t/*\n\t\t\tGet all of the song info elements\n\t\t*/\n\t\tlet songInfoElements = document.querySelectorAll('[amplitude-song-info][amplitude-playlist=\"'+playlist+'\"]');\n\n\t\t/*\n\t\t\tIterate over all of the song info elements. We will either\n\t\t\tset these to the new values, or clear them if the active song\n\t\t\tdoesn't have the info set.\n\t\t*/\n\t\tfor( let i = 0; i < songInfoElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tGet the info so we can check if the active meta data has the\n\t\t\t\tkey.\n\t\t\t*/\n\t\t\tlet info = songInfoElements[i].getAttribute('amplitude-song-info');\n\n\t\t\t/*\n\t\t\t\tGet the song info element playlist.\n\t\t\t*/\n\t\t \tlet elementPlaylist = songInfoElements[i].getAttribute('amplitude-playlist');\n\n\t\t\t/*\n\t\t\t\tIf the playlists match or the element is a main element, then\n\t\t\t\twe set the song info.\n\t\t\t*/\n\t\t\tif( elementPlaylist == playlist ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active metadata has the key, then we set it,\n\t\t\t\t\totherwise we clear it. If it's an image element then\n\t\t\t\t\twe default it to the default info if needed.\n\t\t\t\t*/\n\t\t\t\tif( song[info] != undefined ){\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', song[info]);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = song[info];\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tWe look for the default album art because\n\t\t\t\t\t\tthe actual key didn't exist. If the default album\n\t\t\t\t\t\tart doesn't exist then we set the src attribute\n\t\t\t\t\t\tto null.\n\t\t\t\t\t*/\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tif( song.default_album_art != '' ){\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', song.default_album_art);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', '');\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = '';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the visual playback speed buttons to have the right class\n\t * to display the background image that represents the current playback\n\t * speed.\n\t *\n\t * @access public\n\t */\n\tfunction syncPlaybackSpeed(){\n\t\t/*\n\t\t\tGets all of the playback speed classes.\n\t\t*/\n\t\tlet playbackSpeedClasses = document.getElementsByClassName(\"amplitude-playback-speed\");\n\n\t\t/*\n\t\t\tIterates over all of the playback speed classes\n\t\t\tapplying the right speed class for visual purposes.\n\t\t*/\n\t\tfor( let i = 0; i < playbackSpeedClasses.length; i++ ){\n\t\t\t/*\n\t\t\t\tRemoves all of the old playback speed classes.\n\t\t\t*/\n\t\t\tplaybackSpeedClasses[i].classList.remove('amplitude-playback-speed-10');\n\t\t\tplaybackSpeedClasses[i].classList.remove('amplitude-playback-speed-15');\n\t\t\tplaybackSpeedClasses[i].classList.remove('amplitude-playback-speed-20');\n\n\t\t\t/*\n\t\t\t\tSwitch the current playback speed and apply the appropriate\n\t\t\t\tspeed class.\n\t\t\t*/\n\t\t\tswitch( config.playback_speed ){\n\t\t\t\tcase 1:\n\t\t\t\t\tplaybackSpeedClasses[i].classList.add('amplitude-playback-speed-10');\n\t\t\t\tbreak;\n\t\t\t\tcase 1.5:\n\t\t\t\t\tplaybackSpeedClasses[i].classList.add('amplitude-playback-speed-15');\n\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tplaybackSpeedClasses[i].classList.add('amplitude-playback-speed-20');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the buffered progress bars to the current percentage in the config\n\t *\n\t * @access public\n\t */\n\tfunction syncBufferedProgressBars(){\n\t\t/*\n\t\t\tGets all of the song buffered progress bars.\n\t\t*/\n\t\tlet songBufferedProgressBars = document.getElementsByClassName(\"amplitude-buffered-progress\");\n\n\t\t/*\n\t\t\tIterate over all of the song buffered progress bar and\n\t\t\tset them to 0 which is like re-setting them.\n\t\t*/\n\t\tfor( let i = 0; i < songBufferedProgressBars.length; i++ ){\n\t\t\tsongBufferedProgressBars[i].value = parseFloat( parseFloat( config.buffered ) / 100 );\n\t\t}\n\t}\n\n\t/**\n\t * Visually syncs the volume sliders so they are all the same if there\n\t * are more than one.\n\t *\n\t * @access public\n\t */\n\tfunction syncVolumeSliders(){\n\t\tlet amplitudeVolumeSliders = document.getElementsByClassName(\"amplitude-volume-slider\");\n\n\t\t/*\n\t\t\tIterates over all of the volume sliders for the song, setting the value\n\t\t\tto the config value.\n\t\t*/\n\t\tfor( let i = 0; i < amplitudeVolumeSliders.length; i++ ){\n\t\t\tamplitudeVolumeSliders[i].value = config.active_song.volume * 100;\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the play pause buttons to paused.\n\t *\n\t * @access public\n\t */\n\tfunction setPlayPauseButtonsToPause(){\n\t\t/*\n\t\t\tGets all of the play pause elements\n\t\t*/\n\t\tlet playPauseElements = document.querySelectorAll('.amplitude-play-pause');\n\n\t\t/*\n\t\t\tSets all of the elements to pause\n\t\t*/\n\t\tfor( let i = 0; i < playPauseElements.length; i++ ){\n\t\t\tAmplitudeVisualSyncHelpers.setElementPause( playPauseElements[i] );\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the main play pause buttons to the state of the active song.\n\t *\n\t * @param {string} state The state of the player\n\t * @access public\n\t */\n\tfunction syncMainPlayPause( state ){\n\t\t/*\n\t\t\tEnsures we have a string for the state otherwise we grab the\n\t\t\tstate from the config.\n\t\t*/\n if( typeof state != \"string\" ){\n state = config.active_song.paused ? \"paused\" : \"playing\";\n\t\t}\n\n\t\t/*\n\t\t\tGet all play pause buttons.\n\t\t*/\n\t\tconst playPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-main-play-pause=\"true\"]');\n\n\t\t/*\n\t\t\tIterate over all of the play pause elements syncing the\n\t\t\tdisplay visually.\n\t\t*/\n\t\tfor( let i = 0; i < playPauseElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tDetermines what classes we should add and remove\n\t\t\t\tfrom the elements.\n\t\t\t*/\n\t\t\tswitch( state ){\n\t\t\t\tcase 'playing':\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( playPauseElements[i] );\n\t\t\t\tbreak;\n\t\t\t\tcase 'paused':\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( playPauseElements[i] );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the main playlist play pause buttons to the state of the active song.\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the play pause state for.\n\t * @param {string} state \t\t\t- Either playing or paused for the state of the active song.\n\t */\n\tfunction syncPlaylistPlayPause( playlist, state ){\n\t\t/*\n\t\t\tEnsures we have a string for the state otherwise we grab the\n\t\t\tstate from the config.\n\t\t*/\n if( typeof state != \"string\" ){\n state = config.active_song.paused ? \"paused\" : \"playing\";\n\t\t}\n\n\t\t/*\n\t\t\tGet all of the main playlist play pause elements\n\t\t*/\n\t\tlet playlistPlayPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-playlist-main-play-pause=\"true\"]');\n\n\t\t/*\n\t\t\tIterate over the play pause elements, syncing the state accordingly.\n\t\t*/\n\t\tfor( let i = 0; i < playlistPlayPauseElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the element has the same playlist attribute as the playlist\n\t\t\t\tpassed in and the state is playing, we set the element to\n\t\t\t\tbe playing otherwise we set it to pause. Setting to pause\n\t\t\t\tmeans the element doesn't match the active playlist or the\n\t\t\t\tstate is paused.\n\t\t\t*/\n\t\t\tif( playlistPlayPauseElements[i].getAttribute('amplitude-playlist') == playlist\n\t\t\t\t&& state == 'playing' ){\n\n\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( playlistPlayPauseElements[i] );\n\t\t\t}else{\n\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( playlistPlayPauseElements[i] );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the song play pause buttons to the state of the active song.\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the play pause state for.\n\t * @param {int} song \t\t\t\t\t- The index of the song we are syncing the state for\n\t * @param {string} state \t\t\t- Either playing or paused for the state of the active song.\n\t */\n\tfunction syncSongPlayPause( playlist, song, state ){\n\t\t/*\n\t\t\tEnsures we have a string for the state otherwise we grab the\n\t\t\tstate from the config.\n\t\t*/\n if( typeof state != \"string\" ){\n state = config.active_song.paused ? \"paused\" : \"playing\";\n\t\t}\n\n\t\t/*\n\t\t\tIf the playlist is null or empty, we make sure that any song\n\t\t\tthat is a part of a playlist is set to paused.\n\t\t*/\n\t\tif( playlist == null || playlist == '' ){\n\t\t\t/*\n\t\t\t\tGet all of the individual song play pause buttons. These have an\n\t\t\t\tamplitude-song-index attribute. Some have amplitude-playlist which\n\t\t\t\tmeans they are individual songs within a playlist.\n\t\t\t*/\n\t\t\tlet songPlayPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-song-index]');\n\n\t\t\t/*\n\t\t\t\tIterate over all of the song play pause elements\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songPlayPauseElements.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tIf the song element has an attribute for amplitude-playlist then\n\t\t\t\t\twe set it to paused no matter what because the state of the player\n\t\t\t\t\tis not in a playlist mode.\n\t\t\t\t*/\n\t\t\t\tif( songPlayPauseElements[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the state of the song is playing and the song index matches the\n\t\t\t\t\t\tindex of the song we have, we set the element to playing otherwise\n\t\t\t\t\t\twe set the element to paused.\n\t\t\t\t\t*/\n\t\t\t\t\tif( state == 'playing' && songPlayPauseElements[i].getAttribute('amplitude-song-index') == song ){\n\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( songPlayPauseElements[i] );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tGet all of the individual song play pause buttons. These have an\n\t\t\t\tamplitude-song-index attribute. Some have amplitude-playlist which\n\t\t\t\tmeans they are individual songs within a playlist.\n\t\t\t*/\n\t\t\tlet songPlayPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-song-index]');\n\n\t\t\t/*\n\t\t\t\tIterate over all of the individual play pause elements.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songPlayPauseElements.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tSince we have an active playlist this time, we want any stand alone\n\t\t\t\t\tsongs to be set to paused since the scope is within a playlist.\n\n\t\t\t\t\tWe check to see if the element has an amplitude-playlist attribute.\n\t\t\t\t*/\n\t\t\t\tif( songPlayPauseElements[i].hasAttribute('amplitude-playlist') ){\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the song index matches the index passed in and the\n\t\t\t\t\t\tplaylist matches the scoped playlist we are looking for and the\n\t\t\t\t\t\tstate of the player is playing, then we set the element to play. If those\n\t\t\t\t\t\tthree parameters are not met, set the element to pause.\n\t\t\t\t\t*/\n\t\t\t\t\tif( songPlayPauseElements[i].getAttribute('amplitude-song-index') == song\n\t\t\t\t\t\t&& songPlayPauseElements[i].getAttribute('amplitude-playlist') == playlist\n\t\t\t\t\t\t&& state == 'playing' ){\n\t\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( songPlayPauseElements[i] );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet any individual songs (songs outside of a playlist scope) to pause\n\t\t\t\t\t\tsince we are in the scope of a playlist.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs repeat for all of the repeat buttons. Users\n\t * can apply styles to the 'amplitude-repeat-on' and\n\t * 'amplitude-repeat-off' classes. They represent the state\n\t * of the player.\n\t */\n\tfunction syncRepeat(){\n\t\t/*\n\t\t\tGets all of the repeat classes\n\t\t*/\n\t\tlet repeatClasses = document.getElementsByClassName(\"amplitude-repeat\");\n\n\t\t/*\n\t\t\tIterate over all of the repeat classes. If repeat is on,\n\t\t\tthen add the 'amplitude-repeat-on' class and remove the\n\t\t\t'amplitude-repeat-off' class. If it's off, then do the\n\t\t\topposite.\n\t\t*/\n\t\tfor( let i = 0; i < repeatClasses.length; i++ ){\n\t\t\tif( config.repeat ){\n\t\t\t\trepeatClasses[i].classList.add('amplitude-repeat-on');\n\t\t\t\trepeatClasses[i].classList.remove('amplitude-repeat-off');\n\t\t\t}else{\n\t\t\t\trepeatClasses[i].classList.remove('amplitude-repeat-on');\n\t\t\t\trepeatClasses[i].classList.add('amplitude-repeat-off');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs repeat for all of the playlist repeat buttons. Users\n\t * can apply styles to the `amplitude-repeat-on` and `amplitude-repeat-off`\n\t * classes. They repreent the state of the playlist in the player.\n\t */\n\t function syncRepeatPlaylist( playlist ){\n\t\t /*\n\t\t\t Gets all of the repeat buttons.\n\t\t */\n\t\t let repeatButtons = document.getElementsByClassName(\"amplitude-repeat\");\n\n\t\t /*\n\t\t\t Iterate over all of the repeat buttons\n\t\t */\n\t\t for( let i = 0; i < repeatButtons.length; i++ ){\n\t\t\t /*\n\t\t\t\t Ensure that the repeat button belongs to matches the\n\t\t\t\t playlist we are syncing the state for.\n\t\t\t */\n\t\t\t if( repeatButtons[i].getAttribute('amplitude-playlist') == playlist ){\n\t\t\t\t /*\n\t\t\t\t\t If the state of the playlist is shuffled on, true, then\n\t\t\t\t\t we add the 'amplitude-repeat-on' class and remove the\n\t\t\t\t\t 'amplitude-repeat-off' class. If the player is not shuffled\n\t\t\t\t\t then we do the opposite.\n\t\t\t\t */\n\t\t\t\t if( config.repeat_statuses[playlist] ){\n\t\t\t\t\t repeatButtons[i].classList.add( 'amplitude-repeat-on');\n\t\t\t\t\t repeatButtons[i].classList.remove( 'amplitude-repeat-off');\n\t\t\t\t }else{\n\t\t\t\t\t repeatButtons[i].classList.add( 'amplitude-repeat-off');\n\t\t\t\t\t repeatButtons[i].classList.remove( 'amplitude-repeat-on');\n\t\t\t\t }\n\t\t\t }\n\t\t }\n\t }\n\n\t/**\n\t * Syncs repeat for all of the repeat song buttons. Users\n\t * can apply styles to the 'amplitude-repeat-song-on' and\n\t * 'amplitude-repeat-song-off' classes. They represent the state\n\t * of the player.\n\t */\n\tfunction syncRepeatSong(){\n\t\t/*\n\t\t\tGets all of the repeat song classes\n\t\t*/\n\t\tlet repeatSongClasses = document.getElementsByClassName(\"amplitude-repeat-song\");\n\n\t\t/*\n\t\t\tIterate over all of the repeat song classes. If repeat is on,\n\t\t\tthen add the 'amplitude-repeat-song-on' class and remove the\n\t\t\t'amplitude-repeat-song-off' class. If it's off, then do the\n\t\t\topposite.\n\t\t*/\n\t\tfor( let i = 0; i < repeatSongClasses.length; i++ ){\n\t\t\tif( config.repeat_song ){\n\t\t\t\trepeatSongClasses[i].classList.add('amplitude-repeat-song-on');\n\t\t\t\trepeatSongClasses[i].classList.remove('amplitude-repeat-song-off');\n\t\t\t}else{\n\t\t\t\trepeatSongClasses[i].classList.remove('amplitude-repeat-song-on');\n\t\t\t\trepeatSongClasses[i].classList.add('amplitude-repeat-song-off');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs mute for all of the mute buttons. This represents the\n\t * state of the player if it's muted or not.\n\t *\n\t * @access public\n\t * @param {string} state \t- The muted state of the player.\n\t */\n\tfunction syncMute( state ){\n\t\t/*\n\t\t\tGet all of the mute buttons.\n\t\t*/\n\t\tlet muteClasses = document.getElementsByClassName(\"amplitude-mute\");\n\n\t\t/*\n\t\t\tIterate over all of the mute classes. If the state of the player\n\t\t\tis not-muted then we add the amplitude-not-muted classe and remove\n\t\t\tthe amplitude muted class otherwise we do the opposite.\n\t\t*/\n\t\tfor( let i = 0; i < muteClasses.length; i++ ){\n\t\t\tif( !state ){\n\t\t\t\tmuteClasses[i].classList.add( 'amplitude-not-muted' );\n\t\t\t\tmuteClasses[i].classList.remove( 'amplitude-muted' );\n\t\t\t}else{\n\t\t\t\tmuteClasses[i].classList.remove( 'amplitude-not-muted' );\n\t\t\t\tmuteClasses[i].classList.add( 'amplitude-muted' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the global shuffle button visual state.\n\t *\n\t * @access public\n\t * @param {boolean} state \t- The shuffled state of the player.\n\t */\n\tfunction syncShuffle( state ){\n\t\t/*\n\t\t\tGets the shuffle buttons.\n\t\t*/\n\t\tlet shuffleButtons = document.getElementsByClassName(\"amplitude-shuffle\");\n\n\t\t/*\n\t\t\tIterate over all of the shuffle buttons.\n\t\t*/\n\t\tfor( let i = 0; i < shuffleButtons.length; i++ ){\n\t\t\t/*\n\t\t\t\tEnsure the shuffle button doesn't belong to a playlist. We have\n\t\t\t\ta separate method for that.\n\t\t\t*/\n\t\t\tif( shuffleButtons[i].getAttribute('amplitude-playlist') == null ){\n\t\t\t\t/*\n\t\t\t\t\tIf the state of the player is shuffled on, true, then\n\t\t\t\t\twe add the 'amplitude-shuffle-on' class and remove the\n\t\t\t\t\t'amplitude-shuffle-off' class. If the player is not shuffled\n\t\t\t\t\tthen we do the opposite.\n\t\t\t\t*/\n\t\t\t\tif( state ){\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-on');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-off');\n\t\t\t\t}else{\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-off');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-on');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the playlist shuffle button visual state.\n\t *\n\t * @access public\n\t * @param {boolean} state \t- The shuffled state of the player.\n\t * @param {string} playlist - The playlist string the shuffle button belongs to.\n\t */\n\tfunction syncPlaylistShuffle( state, playlist ){\n\t\t/*\n\t\t\tGets all of the shuffle buttons.\n\t\t*/\n\t\tlet shuffleButtons = document.getElementsByClassName(\"amplitude-shuffle\");\n\n\t\t/*\n\t\t\tIterate over all of the shuffle buttons\n\t\t*/\n\t\tfor( let i = 0; i < shuffleButtons.length; i++ ){\n\t\t\t/*\n\t\t\t\tEnsure that the playlist the shuffle button belongs to matches the\n\t\t\t\tplaylist we are syncing the state for.\n\t\t\t*/\n\t\t\tif( shuffleButtons[i].getAttribute('amplitude-playlist') == playlist ){\n\t\t\t\t/*\n\t\t\t\t\tIf the state of the playlist is shuffled on, true, then\n\t\t\t\t\twe add the 'amplitude-shuffle-on' class and remove the\n\t\t\t\t\t'amplitude-shuffle-off' class. If the player is not shuffled\n\t\t\t\t\tthen we do the opposite.\n\t\t\t\t*/\n\t\t\t\tif( state ){\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-on');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-off');\n\t\t\t\t}else{\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-off');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-on');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the main slider location\n\t *\n\t * @access public\n\t * @param {number} location \t- The location of the song as a percentage.\n\t */\n\tfunction syncMainSliderLocation( location ){\n\t\t/*\n\t\t\tEnsure we have a location that's a number\n\t\t*/\n\t\tlocation = !isNaN( location ) ? location : 0;\n\n\t\t/*\n\t\t\tGets the main song sliders\n\t\t*/\n\t\tlet mainSongSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-main-song-slider=\"true\"]');\n\n\t\t/*\n\t\t\tIterates over all of the main sliders and sets the value to the\n\t\t\tpercentage of the song played.\n\t\t*/\n\t\tfor( let i = 0; i < mainSongSliders.length; i++ ){\n\t\t\tmainSongSliders[i].value = location;\n\t\t}\n\t}\n\n\t/**\n\t * Syncs playlist song slider locations\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the song slider for.\n\t * @param {number} location \t- The location of the song as a percentage.\n\t */\n\tfunction syncPlaylistSliderLocation( playlist, location ){\n\t\t/*\n\t\t\tEnsure we have a location that's a number\n\t\t*/\n\t\tlocation = !isNaN( location ) ? location : 0;\n\n\t\t/*\n\t\t\tGets the playlist song sliders\n\t\t*/\n\t\tlet playlistSongSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-playlist-song-slider=\"true\"][amplitude-playlist=\"'+playlist+'\"]');\n\n\t\t/*\n\t\t\tIterates over all of the playlist sliders and sets the value to the\n\t\t\tpercentage of the song played.\n\t\t*/\n\t\tfor( let i = 0; i < playlistSongSliders.length; i++ ){\n\t\t\tplaylistSongSliders[i].value = location;\n\t\t}\n\t}\n\n\t/**\n\t * Syncs individual song slider locations\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the song slider for.\n\t * @param {number} songIndex \t- The index of the song we are adjusting the song slider for.\n\t * @param {number} location \t- The location of the song as a percentage.\n\t */\n\tfunction syncSongSliderLocation( playlist, songIndex, location ){\n\t\t/*\n\t\t\tEnsure we have a location that's a number\n\t\t*/\n\t\tlocation = !isNaN( location ) ? location : 0;\n\t\t/*\n\t\t\tIf the playlist is set, we get all of the individual song sliders\n\t\t\tthat relate to the song and the playlist.\n\t\t*/\n\t\tif( playlist != '' && playlist != null ){\n\t\t\t/*\n\t\t\t\tGets the song sliders for the individual songs and the\n\t\t\t\tplaylist\n\t\t\t*/\n\t\t\tlet songSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-playlist=\"'+playlist+'\"][amplitude-song-index=\"'+songIndex+'\"]');\n\n\t\t\t/*\n\t\t\t\tIterates over all of the playlist sliders and set the value to the\n\t\t\t\tpercentage of the song played.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songSliders.length; i++ ){\n\t\t\t\tsongSliders[i].value = location;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tGet the individual song slider by index\n\t\t\t*/\n\t\t\tlet songSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-song-index=\"'+songIndex+'\"]');\n\n\t\t\t/*\n\t\t\t\tIterats over all of the song sliders that have the index of\n\t\t\t\tthe song we are sliding. If the song doesn't have a playlist\n\t\t\t\tattribute, we set the location.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songSliders.length; i++ ){\n\t\t\t\tif( !songSliders[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\tif( location != 0 ){\n\t\t\t\t\t\tsongSliders[i].value = location;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the volume slider location\n\t *\n\t * @access public\n\t * @param {number} volume \t- The volume from 0 - 1 for song volume.\n\t */\n\tfunction syncVolumeSliderLocation( volume ){\n\t\t/*\n\t\t\tGets all of the volume sliders\n\t\t*/\n\t\tlet volumeSliders = document.querySelectorAll('.amplitude-volume-slider');\n\n\t\t/*\n\t\t\tIterates over all of the sliders and sets their volume\n\t\t\tto the volume of the song.\n\t\t*/\n\t\tfor( let i = 0; i < volumeSliders.length; i++ ){\n\t\t\tvolumeSliders[i].value = volume;\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the song's duration\n\t *\n\t * @access public\n\t * @param {object} currentTime \t\t- Object containing information about the current time of the song.\n\t * @param {object} songDuration \t- Object containing information about the duration of the song.\n\t */\n\tfunction syncSongDuration( currentTime, songDuration ){\n\t\t/*\n\t\t\tSet duration hour display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationHours( songDuration != undefined && !isNaN( songDuration.hours ) ? songDuration.hours : '00' );\n\n\t\t/*\n\t\t\tSet duration minute display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationMinutes( songDuration != undefined && !isNaN( songDuration.minutes ) ? songDuration.minutes : '00' );\n\n\t\t/*\n\t\t\tSet duration second display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationSeconds( songDuration != undefined && !isNaN( songDuration.seconds ) ? songDuration.seconds : '00' );\n\n\t\t/*\n\t\t\tSet duration time display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationTime( songDuration != undefined ? songDuration : {} );\n\n\t\t/*\n\t\t\tSet count down time display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCountDownTime( currentTime, songDuration );\n\t}\n\n\t/**\n\t * Sets the meta data for songs loaded in the songs array\n\t */\n\t function syncSongsMetaData(){\n\t\t /*\n \t\t\tDefine the image meta data keys. These are managed separately\n \t\t\tsince we aren't actually changing the inner HTML of these elements.\n \t\t*/\n \t\tlet imageMetaDataKeys \t= ['cover_art_url', 'station_art_url', 'podcast_episode_cover_art_url'];\n\n \t\t/*\n \t\t\tThese are the ignored keys that we won't be worrying about displaying.\n \t\t\tEvery other key in the song object can be displayed.\n \t\t*/\n \t\tlet ignoredKeys \t\t= ['url', 'live'];\n\n \t\t/*\n \t\t\tGet all of the song info elements\n \t\t*/\n \t\tlet songInfoElements = document.querySelectorAll('[amplitude-song-info]');\n\n \t\t/*\n \t\t\tIterate over all of the song info elements. We will either\n \t\t\tset these to the new values, or clear them if the active song\n \t\t\tdoesn't have the info set.\n \t\t*/\n \t\tfor( let i = 0; i < songInfoElements.length; i++ ){\n\n\t\t\t/*\n\t\t\t\tFor this method we do not want the element to have any playlist or\n\t\t\t\tmain song info. This way we aren't adjusting the main song information for the\n\t\t\t\tglobal player or the playlist player.\n\t\t\t*/\n\t\t\tif( songInfoElements[i].getAttribute('amplitude-playlist') == null\n\t\t\t\t\t&& songInfoElements[i].getAttribute('amplitude-main-song-info') == null\n\t\t\t\t && songInfoElements[i].getAttribute('amplitude-song-index') != null ){\n\n\t\t\t\t\t/*\n\t\t \t\t\t\tGet the info so we can check if the active meta data has the\n\t\t \t\t\t\tkey.\n\t\t \t\t\t*/\n\t\t \t\t\tlet info = songInfoElements[i].getAttribute('amplitude-song-info');\n\t\t\t\t\tlet index = songInfoElements[i].getAttribute('amplitude-song-index');\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tMake sure that the song index they are referencing is defined.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.songs[index][info] != undefined ){\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tIf it's an image meta data key, then we set the src attribute of\n\t\t\t\t\t\t\tthe element. Otherwise we set the inner HTML of the element.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', config.songs[index][info]);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsongInfoElements[i].innerHTML = config.songs[index][info];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t \t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t\tReturns the publically available functions\n\t\t@TODO Re-order to order of methods in module\n\t*/\n\treturn {\n\t\tsyncCurrentTime: syncCurrentTime,\n\t\tresetTimes: resetTimes,\n\t\tresetSongSliders: resetSongSliders,\n\t\tresetSongPlayedProgressBars: resetSongPlayedProgressBars,\n\t\tresetSongBufferedProgressBars: resetSongBufferedProgressBars,\n\t\tsetActiveContainer: setActiveContainer,\n\t\tdisplaySongMetadata: displaySongMetadata,\n\t\tsyncPlaybackSpeed: syncPlaybackSpeed,\n\t\tsyncBufferedProgressBars: syncBufferedProgressBars,\n\t\tsyncVolumeSliders: syncVolumeSliders,\n\t\tsetPlayPauseButtonsToPause: setPlayPauseButtonsToPause,\n\t\tsetFirstSongInPlaylist: setFirstSongInPlaylist,\n\t\tsyncMainPlayPause: syncMainPlayPause,\n\t\tsyncPlaylistPlayPause: syncPlaylistPlayPause,\n\t\tsyncSongPlayPause: syncSongPlayPause,\n\t\tsyncRepeat: syncRepeat,\n\t\tsyncRepeatSong: syncRepeatSong,\n\t\tsyncRepeatPlaylist: syncRepeatPlaylist,\n\t\tsyncMute: syncMute,\n\t\tsyncShuffle: syncShuffle,\n\t\tsyncPlaylistShuffle: syncPlaylistShuffle,\n\t\tsyncMainSliderLocation: syncMainSliderLocation,\n\t\tsyncPlaylistSliderLocation: syncPlaylistSliderLocation,\n\t\tsyncSongSliderLocation: syncSongSliderLocation,\n\t\tsyncVolumeSliderLocation: syncVolumeSliderLocation,\n\t\tsyncSongDuration: syncSongDuration,\n\t\tsyncSongsMetaData: syncSongsMetaData\n\t}\n})();\n\nexport default AmplitudeVisualSync\n\n\n\n// WEBPACK FOOTER //\n// ./src/visual/visual.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * AmplitudeJS Core Helpers\n * @module core/helpers\n */\nimport AmplitudeHelpers from './helpers.js';\n\n/**\n * AmplitudeJS Visual Sync\n * @module visual/visual\n*/\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * Interacts directly with native functions of the Audio element. Logic\n * leading up to these methods are handled by click handlers which call\n * helpers and visual synchronizers. These are the core functions of AmplitudeJS.\n * Every other function that leads to these prepare the information to be\n * acted upon by these functions.\n *\n * @module core/AmplitudeCore\n */\nlet AmplitudeCore = (function() {\n\t/**\n\t * Plays the active song. If the current song is live, it reconnects\n\t * the stream before playing.\n\t *\n\t * Public Accessor: Amplitude.play()\n\t *\n\t * @access public\n\t */\n\tfunction play(){\n\t\t/*\n\t\t\tRun the before play callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('before_play');\n\n\t\t/*\n\t\t\tIf the audio is live we re-conenct the stream.\n\t\t*/\n\t\tif( config.active_metadata.live ){\n\t\t\treconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tMobile remote sources need to be reconnected on play. I think this is\n\t\t\tbecause mobile browsers are optimized not to load all resources\n\t\t\tfor speed reasons. We only do this if mobile and the paused button\n\t\t\tis not clicked. If the pause button was clicked then we don't reconnect\n\t\t\tor the user will lose their place in the stream.\n\t\t*/\n\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && !config.paused ) {\n\t\t\treconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tPlay the song and set the playback rate to the playback\n\t\t\tspeed.\n\t\t*/\n\t\tconfig.active_song.play();\n\t\tconfig.active_song.playbackRate = config.playback_speed;\n\n\t\t/*\n\t\t\tRun the after play callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_play');\n\t}\n\n\t/**\n\t * Pauses the active song. If it's live, it disconnects the stream.\n\t *\n\t * Public Accessor: Amplitude.pause()\n\t *\n\t * @access public\n\t */\n\tfunction pause(){\n\t\t/*\n\t\t\tRun the before pause callback.\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('before_pause');\n\n\t\t/*\n\t\t\tPause the active song.\n\t\t*/\n\t\tconfig.active_song.pause();\n\n\t\t/*\n\t\t\tFlag that pause button was clicked.\n\t\t*/\n\t\tconfig.paused = true;\n\n\t\t/*\n\t\t\tIf the song is live, we disconnect the stream so we aren't\n\t\t\tsaving it to memory.\n\t\t*/\n\t\tif( config.active_metadata.live ){\n\t\t\tdisconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tRun the after pause callback.\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_pause');\n\t}\n\n\t/**\n\t * Stops the active song by setting the current song time to 0.\n\t * When the user resumes, it will be from the beginning.\n\t * If it's a live stream it disconnects.\n\t *\n\t * Public Accessor: Amplitude.stop()\n\t *\n\t * @access public\n\t */\n\tfunction stop(){\n\t\t/*\n\t\t\tRuns the before stop callback.\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('before_stop');\n\n\t\t/*\n\t\t\tSet the current time of the song to 0 which will reset the song.\n\t\t*/\n\t\tif( config.active_song.currentTime != 0 ){\n\t\t\tconfig.active_song.currentTime = 0;\n\t\t}\n\n\t\t/*\n\t\t\tRun pause so the song will stop\n\t\t*/\n\t\tconfig.active_song.pause();\n\n\t\t/*\n\t\t\tIf the song is live, disconnect the stream.\n\t\t*/\n\t\tif( config.active_metadata.live ){\n\t\t\tdisconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tRun the after stop callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_stop');\n\t}\n\n\t/**\n\t * Sets the song volume.\n\t *\n\t * Public Accessor: Amplitude.setVolume( volumeLevel )\n\t *\n\t * @access public\n\t * @param {number} volumeLevel - A number between 1 and 100 as a percentage of\n\t * min to max for a volume level.\n\t */\n\tfunction setVolume( volumeLevel ){\n\t\t/*\n\t\t\tIf the volume is set to mute somewhere else, we sync the display.\n\t\t*/\n\t\tif( volumeLevel == 0 ){\n\t\t\tAmplitudeVisualSync.syncMute( true );\n\t\t}else{\n\t\t\tAmplitudeVisualSync.syncMute( false );\n\t\t}\n\n\t\t/*\n\t\t\tSet the volume of the active song.\n\t\t*/\n\t\tconfig.active_song.volume = volumeLevel / 100;\n\t}\n\n\t/**\n\t * Sets the song percentage. If it's a live song, we ignore this because\n\t * we can't skip ahead. This is an issue if you have a playlist with\n\t * a live source.\n\t *\n\t * Public Accessor: Amplitude.setSongLocation( songPercentage )\n\t *\n\t * @access public\n\t * @param {number} songPercentage - A number between 1 and 100 as a percentage of song completion.\n\t */\n\tfunction setSongLocation( songPercentage ){\n\t\t/*\n\t\t\tAs long as the song is not live, we can set the current time of the\n\t\t\tsong to the percentage the user passed in.\n\t\t*/\n\t\tif( !config.active_metadata.live ){\n\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( song_percentage / 100 );\n\t\t}\n\t}\n\n\t/**\n\t * Skips to a location in a song\n\t *\n\t * Public Accessor: Amplitude.skipToLocation( seconds )\n\t *\n\t * @access public\n\t * @param {number} seconds - An integer containing the seconds to skip to\n\t */\n\tfunction skipToLocation( seconds ){\n\t\t/*\n\t\t\tWhen the active song can be played through, we can check to\n\t\t\tsee if the seconds will work. We only bind the event handler\n\t\t\tonce and remove it once it's fired.\n\t\t*/\n\t\tconfig.active_song.addEventListener('canplaythrough', function(){\n\t\t\t/*\n\t\t\t\tIf the active song duration is greater than or equal to the\n\t\t\t\tamount of seconds the user wants to skip to and the seconds\n\t\t\t\tis greater than 0, we skip to the seconds defined.\n\t\t\t*/\n\t\t\tif( config.active_song.duration >= seconds && seconds > 0 ){\n\t\t\t\tconfig.active_song.currentTime = seconds;\n\t\t\t}else{\n\t\t\t\tAmplitudeHelpers.writeDebugMessage('Amplitude can\\'t skip to a location greater than the duration of the audio or less than 0');\n\t\t\t}\n\t\t}, { once: true });\n\t}\n\n\t/**\n\t * Disconnects the live stream\n\t *\n\t * Public Accessor: Amplitude.disconnectStream()\n\t *\n\t * @access public\n\t */\n\tfunction disconnectStream(){\n\t\tconfig.active_song.src = '';\n\t\tconfig.active_song.load();\n\t}\n\n\t/**\n\t * Reconnects the live stream\n\t *\n\t * Public Accessor: Amplitude.reconnectStream()\n\t *\n\t * @access public\\\n\t */\n\tfunction reconnectStream(){\n\t\tconfig.active_song.src = config.active_metadata.url;\n\t\tconfig.active_song.load();\n\t}\n\n\t/**\n\t * When you pass a song object it plays that song right awawy. It sets\n\t * the active song in the config to the song you pass in and synchronizes\n\t * the visuals.\n\t *\n\t * Public Accessor: Amplitude.playNow( song )\n\t *\n\t * @access public\n\t * @param {object} song - JSON representation of a song.\n\t */\n\tfunction playNow( song ){\n\t\t/*\n\t\t\tMakes sure the song object has a URL associated with it\n\t\t\tor there will be nothing to play.\n\t\t*/\n\t\tif( song.url ){\n\t\t\tconfig.active_song.src \t= song.url;\n\t\t\tconfig.active_metadata \t= song;\n\t\t\tconfig.active_album \t= song.album;\n\t\t}else{\n\t\t\t/*\n\t\t\t\tWrite error message since the song passed in doesn't\n\t\t\t\thave a URL.\n\t\t\t*/\n\t\t\tAmplitudeHelpers.writeDebugMessage('The song needs to have a URL!');\n\t\t}\n\n\t\t/*\n\t\t\tSets the main song control status visual\n\t\t*/\n\t\tAmplitudeVisualSync.syncMainPlayPause('playing');\n\n\t\t/*\n\t\t\tUpdate the song meta data\n\t\t*/\n\t\tAmplitudeVisualSync.displaySongMetadata();\n\n\n\t\t/*\n\t\t\tReset the song sliders, song progress bar info, and\n\t\t\treset times. This ensures everything stays in sync.\n\t\t*/\n\t\tAmplitudeVisualSync.resetSongSliders();\n\n\t\tAmplitudeVisualSync.resetSongPlayedProgressBars();\n\n\t\tAmplitudeVisualSync.resetTimes();\n\n\t\t/*\n\t\t\tPlays the song.\n\t\t*/\n\t\tplay();\n\t}\n\n\t/**\n\t * Plays the song at a specific index in the songs array\n\t *\n\t * Public Accessor: Amplitude.playSongAtIndex( song )\n\t *\n\t * @access public\n\t * @param {number} index - The number representing the song in the songs array\n\t */\n\t function playSongAtIndex( index ){\n\t\t /*\n\t\t\t\tStop the current song.\n\t\t */\n\t\t stop();\n\n\t\t /*\n\t\t\t\tDetermine if there is a new playlist, if so set the active playlist and change the song.\n\t\t */\n\t\t if( AmplitudeHelpers.checkNewPlaylist( null ) ){\n\t\t\t AmplitudeHelpers.setActivePlaylist( null );\n\n\t\t\t AmplitudeHelpers.changeSong( index );\n\t\t }\n\n\t\t /*\n\t\t\t\tCheck if the song is new. If so, change the song.\n\t\t */\n\t\t if( AmplitudeHelpers.checkNewSong( index ) ){\n\t\t\t AmplitudeHelpers.changeSong( index );\n\t\t }\n\n\t\t /*\n\t\t\t Sync all of the play pause buttons.\n\t\t */\n\t\t AmplitudeVisualSync.syncMainPlayPause('playing');\n\t\t AmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\t\t AmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t /*\n\t\t\t Play the song\n\t\t */\n\t\t play();\n\t }\n\n\t /**\n\t\t* Plays a song at the index passed in for the playlist provided. The index passed\n\t\t* in should be the index of the song in the playlist and not the songs array.\n\t\t*\n\t\t* @access public\n\t\t* @param {number} index \t\t- The number representing the song in the playlist array.\n\t\t* @param {string} playlist \t- The key string representing the playlist we are playing the song from.\n\t\t*\n\t\t*/\n\t function playPlaylistSongAtIndex( index, playlist ){\n\t\t\t /*\n\t\t\t \t\tStop the current song.\n\t\t\t */\n\t\t\t stop();\n\n\t\t\t /*\n\t\t\t \t\tGet the index of the song in the songs array. This is the integer at the index\n\t\t\t\t\tin the playlist.\n\t\t\t */\n\t\t\t let songIndex = config.playlists[ playlist ][ index ];\n\n\t\t\t /*\n\t\t\t \t\tDetermine if there is a new playlist, if so set the active playlist and change the song.\n\t\t\t */\n\t\t\t if( AmplitudeHelpers.checkNewPlaylist( playlist ) ){\n\t\t\t\t AmplitudeHelpers.setActivePlaylist( playlist );\n\n\t\t\t\t AmplitudeHelpers.changeSong( songIndex );\n\t\t\t }\n\n\t\t\t /*\n\t\t\t \t\tCheck if the song is new. If so, change the song.\n\t\t\t */\n\t\t\tif( AmplitudeHelpers.checkNewSong( songIndex ) ){\n\t\t\t AmplitudeHelpers.changeSong( songIndex );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSync all of the play pause buttons.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause('playing');\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tplay();\n\t }\n\n\t/**\n\t * Sets the playback speed for the song.\n\t *\n\t * @param {number} playbackSpeed The speed we want the song to play back at.\n\t */\n\tfunction setPlaybackSpeed( playbackSpeed ){\n\t\t/*\n\t\t\tSet the config playback speed.\n\t\t*/\n\t\tconfig.playback_speed = playbackSpeed;\n\n\t\t/*\n\t\t\tSet the active song playback rate.\n\t\t*/\n\t\tconfig.active_song.playbackRate = config.playback_speed;\n\t}\n\n\t/*\n\t\tReturn publically facing functions\n\t*/\n\treturn {\n\t\tplay: play,\n\t\tpause: pause,\n\t\tstop: stop,\n\t\tsetVolume: setVolume,\n\t\tsetSongLocation: setSongLocation,\n\t\tskipToLocation: skipToLocation,\n\t\tdisconnectStream: disconnectStream,\n\t\treconnectStream: reconnectStream,\n\t\tplayNow: playNow,\n\t\tplaySongAtIndex: playSongAtIndex,\n\t\tplayPlaylistSongAtIndex: playPlaylistSongAtIndex,\n\t\tsetPlaybackSpeed: setPlaybackSpeed\n\t}\n})();\n\nexport default AmplitudeCore\n\n\n\n// WEBPACK FOOTER //\n// ./src/core/core.js","/*\n\tImport the necessary classes and config to use\n\twith the events.\n*/\nimport config from '../config.js';\nimport AmplitudeHelpers from '../core/helpers.js';\nimport AmplitudeHandlers from './handlers.js';\n\n/*\n|----------------------------------------------------------------------------------------------------\n| EVENTS METHODS\n|----------------------------------------------------------------------------------------------------\n| These methods are called when we need to bind events to certain elements.\n|\n| METHODS:\n| \tinitializeEvents()\n|\tbindPlay()\n|\tbindPause()\n|\tbindPlayPause()\n|\tbindStop()\n|\tbindMute()\n|\tbindVolumeUp()\n|\tbindVolumeDown()\n|\tbindSongSlider()\n|\tbindVolumeSlider()\n|\tbindNext()\n|\tbindPrev()\n|\tbindShuffle()\n|\tbindRepeat()\n|\tbindPlaybackSpeed()\n|\tbindSkipTo()\n| bindProgress()\n*/\nvar AmplitudeEvents = (function () {\n\t/*--------------------------------------------------------------------------\n\t\tInitializes the handlers for the events listened to by Amplitude\n\t--------------------------------------------------------------------------*/\n\tfunction initializeEvents(){\n\t\t/*\n\t\t\tWrite out debug message\n\t\t*/\n\t\tAmplitudeHelpers.writeDebugMessage( 'Beginning initialization of event handlers..' );\n\n\t\t/*\n\t\t\tSets flag that the screen is moving and not a tap\n\t\t*/\n\t\tdocument.addEventListener('touchmove', function(){\n\t\t\tconfig.is_touch_moving = true;\n\t\t});\n\n\t\t/*\n\t\t\tOn touch end if it was a touch move event, set moving to\n\t\t\tfalse\n\t\t*/\n\t\tdocument.addEventListener('touchend', function(){\n\t\t\tif( config.is_touch_moving ){\n\t\t\t\tconfig.is_touch_moving = false;\n\t\t\t}\n\t\t});\n\n\t\t/*\n\t\t\tOn time update for the audio element, update visual displays that\n\t\t\trepresent the time on either a visualized element or time display.\n\t\t*/\n\t\tbindTimeUpdate();\n\n\t\t/*\n\t\t\tBinds key down event handlers for matching key codes to functions.\n\t\t*/\n\t\tbindKeyDownEventHandlers();\n\n\t\t/*\n\t\t\tWhen the audio element has ended playing, we handle the song\n\t\t\tending. In a single song or multiple modular song instance,\n\t\t\tthis just synchronizes the visuals for time and song time\n\t\t\tvisualization, but for a playlist it determines whether\n\t\t\tit should play the next song or not.\n\t\t*/\n\t\tbindSongEnded();\n\n\t\t/*\n\t\t\tBinds progress event so we can see how much of the song is loaded.\n\t\t*/\n\t\tbindProgress();\n\n\t\t/*\n\t\t\tBinds 'amplitude-play' event handlers\n\t\t*/\n\t\tbindPlay();\n\n\t\t/*\n\t\t\tBinds 'amplitude-pause' event handlers.\n\t\t*/\n\t\tbindPause();\n\n\t\t/*\n\t\t\tBinds 'amplitude-play-pause' event handlers.\n\t\t*/\n\t\tbindPlayPause();\n\n\t\t/*\n\t\t\tBinds 'amplitude-stop' event handlers.\n\t\t*/\n\t\tbindStop();\n\n\t\t/*\n\t\t\tBinds 'amplitude-mute' event handlers.\n\t\t*/\n\t\tbindMute();\n\n\t\t/*\n\t\t\tBinds 'amplitude-volume-up' event handlers\n\t\t*/\n\t\tbindVolumeUp();\n\n\t\t/*\n\t\t\tBinds 'amplitude-volume-down' event handlers\n\t\t*/\n\t\tbindVolumeDown();\n\n\t\t/*\n\t\t\tBinds 'amplitude-song-slider' event handlers\n\t\t*/\n\t\tbindSongSlider();\n\n\t\t/*\n\t\t\tBinds 'amplitude-volume-slider' event handlers.\n\t\t*/\n\t\tbindVolumeSlider();\n\n\t\t/*\n\t\t\tBinds 'amplitude-next' event handlers.\n\t\t*/\n\t\tbindNext();\n\n\t\t/*\n\t\t\tBinds 'amplitude-prev' event handlers.\n\t\t*/\n\t\tbindPrev();\n\n\t\t/*\n\t\t\tBinds 'amplitude-shuffle' event handlers.\n\t\t*/\n\t\tbindShuffle();\n\n\t\t/*\n\t\t\tBinds 'amplitude-repeat' event handlers.\n\t\t*/\n\t\tbindRepeat();\n\n\t\t/*\n\t\t\tBinds 'amplitude-playback-speed' event handlers.\n\t\t*/\n\t\tbindPlaybackSpeed();\n\n\t\t/*\n\t\t\tBinds 'amplitude-skip-to' event handlers.\n\t\t*/\n\t\tbindSkipTo();\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tOn time update for the audio element, update visual displays that\n\t\t\trepresent the time on either a visualized element or time display.\n\t--------------------------------------------------------------------------*/\n\tfunction bindTimeUpdate(){\n\t\tconfig.active_song.removeEventListener( 'timeupdate', AmplitudeHandlers.updateTime );\n\t\tconfig.active_song.addEventListener( 'timeupdate', AmplitudeHandlers.updateTime );\n\n // also bind change of duratuion\n\t\tconfig.active_song.removeEventListener( 'durationchange', AmplitudeHandlers.updateTime );\n\t\tconfig.active_song.addEventListener( 'durationchange', AmplitudeHandlers.updateTime );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tOn keydown, we listen to what key got pressed so we can map the key to\n\t\ta function. This allows the user to map pause and play, next, etc. to key\n\t\tpresses.\n\t--------------------------------------------------------------------------*/\n\tfunction bindKeyDownEventHandlers(){\n\t\tdocument.removeEventListener(\"keydown\", AmplitudeHelpers.keydown );\n\t\tdocument.addEventListener(\"keydown\", AmplitudeHandlers.keydown );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tWhen the audio element has ended playing, we handle the song\n\t\tending. In a single song or multiple modular song instance,\n\t\tthis just synchronizes the visuals for time and song time\n\t\tvisualization, but for a playlist it determines whether\n\t\tit should play the next song or not.\n\t--------------------------------------------------------------------------*/\n\tfunction bindSongEnded(){\n\t\tconfig.active_song.removeEventListener( 'ended', AmplitudeHandlers.songEnded );\n\t\tconfig.active_song.addEventListener( 'ended', AmplitudeHandlers.songEnded );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tAs the audio is loaded, the progress event gets fired. We bind into this\n\t\tto grab the buffered percentage of the song. We can then add more elements\n\t\tto show the buffered amount.\n\t--------------------------------------------------------------------------*/\n\tfunction bindProgress(){\n\t\tconfig.active_song.removeEventListener( 'progress', AmplitudeHandlers.progess );\n\t\tconfig.active_song.addEventListener( 'progress', AmplitudeHandlers.progress );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-play\"\n\n\t\tBinds click and touchend events for amplitude play buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPlay(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-play\n\t\t*/\n\t\tvar play_classes = document.getElementsByClassName(\"amplitude-play\");\n\n\t\t/*\n\t\t\tIterates over all of the play classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < play_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent ) ) {\n\t\t\t\tplay_classes[i].removeEventListener('touchend', AmplitudeHandlers.play );\n\t\t\t\tplay_classes[i].addEventListener('touchend', AmplitudeHandlers.play );\n\t\t\t}else{\n\t\t\t\tplay_classes[i].removeEventListener('click', AmplitudeHandlers.play );\n\t\t\t\tplay_classes[i].addEventListener('click', AmplitudeHandlers.play );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-pause\"\n\n\t\tBinds click and touchend events for amplitude pause buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPause(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-pause\n\t\t*/\n\t\tvar pause_classes = document.getElementsByClassName(\"amplitude-pause\");\n\n\t\t/*\n\t\t\tIterates over all of the pause classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < pause_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tpause_classes[i].removeEventListener('touchend', AmplitudeHandlers.pause );\n\t\t\t\tpause_classes[i].addEventListener('touchend', AmplitudeHandlers.pause );\n\t\t\t}else{\n\t\t\t\tpause_classes[i].removeEventListener('click', AmplitudeHandlers.pause );\n\t\t\t\tpause_classes[i].addEventListener('click', AmplitudeHandlers.pause );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-play-pause\"\n\n\t\tBinds click and touchend events for amplitude play pause buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPlayPause(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-play-pause\n\t\t*/\n\t\tvar play_pause_classes = document.getElementsByClassName(\"amplitude-play-pause\");\n\n\t\t/*\n\t\t\tIterates over all of the play/pause classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < play_pause_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tplay_pause_classes[i].removeEventListener('touchend', AmplitudeHandlers.playPause );\n\t\t\t\tplay_pause_classes[i].addEventListener('touchend', AmplitudeHandlers.playPause );\n\t\t\t}else{\n\t\t\t\tplay_pause_classes[i].removeEventListener('click', AmplitudeHandlers.playPause );\n\t\t\t\tplay_pause_classes[i].addEventListener('click', AmplitudeHandlers.playPause );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-stop\"\n\n\t\tBinds click and touchend events for amplitude stop buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindStop(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-stop\n\t\t*/\n\t\tvar stop_classes = document.getElementsByClassName(\"amplitude-stop\");\n\n\t\t/*\n\t\t\tIterates over all of the stop classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < stop_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tstop_classes[i].removeEventListener('touchend', AmplitudeHandlers.stop );\n\t\t\t\tstop_classes[i].addEventListener('touchend', AmplitudeHandlers.stop );\n\t\t\t}else{\n\t\t\t\tstop_classes[i].removeEventListener('click', AmplitudeHandlers.stop );\n\t\t\t\tstop_classes[i].addEventListener('click', AmplitudeHandlers.stop );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-mute\"\n\n\t\tBinds click and touchend events for amplitude mute buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindMute(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitue-mute\n\t\t*/\n\t\tvar mute_classes = document.getElementsByClassName(\"amplitude-mute\");\n\n\t\t/*\n\t\t\tIterates over all of the mute classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < mute_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\t/*\n\t\t\t\t\tChecks for an iOS device and displays an error message if debugging\n\t\t\t\t\tis turned on.\n\t\t\t\t*/\n\t\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t\t}else{\n\t\t\t\t\tmute_classes[i].removeEventListener('touchend', AmplitudeHandlers.mute );\n\t\t\t\t\tmute_classes[i].addEventListener('touchend', AmplitudeHandlers.mute );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tmute_classes[i].removeEventListener('click', AmplitudeHandlers.mute );\n\t\t\t\tmute_classes[i].addEventListener('click', AmplitudeHandlers.mute );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-volume-up\"\n\n\t\tBinds click and touchend events for amplitude volume up buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindVolumeUp(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-volume-up\n\t\t*/\n\t\tvar volume_up_classes = document.getElementsByClassName(\"amplitude-volume-up\");\n\n\t\t/*\n\t\t\tIterates over all of the volume up classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < volume_up_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\t/*\n\t\t\t\t\tChecks for an iOS device and displays an error message if debugging\n\t\t\t\t\tis turned on.\n\t\t\t\t*/\n\t\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t\t}else{\n\t\t\t\t\tvolume_up_classes[i].removeEventListener('touchend', AmplitudeHandlers.volumeUp );\n\t\t\t\t\tvolume_up_classes[i].addEventListener('touchend', AmplitudeHandlers.volumeUp );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tvolume_up_classes[i].removeEventListener('click', AmplitudeHandlers.volumeUp );\n\t\t\t\tvolume_up_classes[i].addEventListener('click', AmplitudeHandlers.volumeUp );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-volume-down\"\n\n\t\tBinds click and touchend events for amplitude volume down buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindVolumeDown(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-volume-down\n\t\t*/\n\t\tvar volume_down_classes = document.getElementsByClassName(\"amplitude-volume-down\");\n\n\t\t/*\n\t\t\tIterates over all of the volume down classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < volume_down_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\t/*\n\t\t\t\t\tChecks for an iOS device and displays an error message if debugging\n\t\t\t\t\tis turned on.\n\t\t\t\t*/\n\t\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t\t}else{\n\t\t\t\t\tvolume_down_classes[i].removeEventListener('touchend', AmplitudeHandlers.volumeDown );\n\t\t\t\t\tvolume_down_classes[i].addEventListener('touchend', AmplitudeHandlers.volumeDown );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tvolume_down_classes[i].removeEventListener('click', AmplitudeHandlers.volumeDown );\n\t\t\t\tvolume_down_classes[i].addEventListener('click', AmplitudeHandlers.volumeDown );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-song-slider\"\n\n\t\tBinds change and input events for amplitude song slider inputs\n\t--------------------------------------------------------------------------*/\n\tfunction bindSongSlider(){\n\t\t/*\n\t\t\tGets browser so if we need to apply overrides, like we usually\n\t\t\thave to do for anything cool in IE, we can do that.\n\t\t*/\n\t\tvar ua \t\t= window.navigator.userAgent;\n var msie \t= ua.indexOf(\"MSIE \");\n\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-song-slider\n\t\t*/\n\t\tvar song_sliders = document.getElementsByClassName(\"amplitude-song-slider\");\n\n\t\t/*\n\t\t\tIterates over all of the song slider classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is IE we listen to the change event\n\t\t\twhere if it is anything else, it's the input method.\n\t\t*/\n\t\tfor( var i = 0; i < song_sliders.length; i++ ){\n\t\t\tif ( msie > 0 || !!navigator.userAgent.match(/Trident.*rv\\:11\\./) ){\n\t\t\t\tsong_sliders[i].removeEventListener('change', AmplitudeHandlers.songSlider );\n\t\t\t\tsong_sliders[i].addEventListener('change', AmplitudeHandlers.songSlider );\n\t\t\t}else{\n\t\t\t\tsong_sliders[i].removeEventListener('input', AmplitudeHandlers.songSlider );\n\t\t\t\tsong_sliders[i].addEventListener('input', AmplitudeHandlers.songSlider );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-volume-slider\"\n\n\t\tBinds change and input events for amplitude volume slider inputs\n\t--------------------------------------------------------------------------*/\n\tfunction bindVolumeSlider(){\n\t\t/*\n\t\t\tGets browser so if we need to apply overrides, like we usually\n\t\t\thave to do for anything cool in IE, we can do that.\n\t\t*/\n\t\tvar ua \t\t= window.navigator.userAgent;\n var msie \t= ua.indexOf(\"MSIE \");\n\n /*\n\t\t\tGets all of the elements with the class amplitude-volume-slider\n */\n\t\tvar volume_sliders = document.getElementsByClassName(\"amplitude-volume-slider\");\n\n\t\t/*\n\t\t\tIterates over all of the volume slider classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is IE we listen to the change event\n\t\t\twhere if it is anything else, it's the input method.\n\t\t*/\n\t\tfor( var i = 0; i < volume_sliders.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t}else{\n\t\t\t\tif ( msie > 0 || !!navigator.userAgent.match(/Trident.*rv\\:11\\./) ){\n\t\t\t\t\tvolume_sliders[i].removeEventListener('change', AmplitudeHandlers.volumeSlider );\n\t\t\t\t\tvolume_sliders[i].addEventListener('change', AmplitudeHandlers.volumeSlider );\n\t\t\t\t}else{\n\t\t\t\t\tvolume_sliders[i].removeEventListener('input', AmplitudeHandlers.volumeSlider );\n\t\t\t\t\tvolume_sliders[i].addEventListener('input', AmplitudeHandlers.volumeSlider );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-next\"\n\n\t\tBinds click and touchend events for amplitude next buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindNext(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-next\n */\n\t\tvar next_classes = document.getElementsByClassName(\"amplitude-next\");\n\n\t\t/*\n\t\t\tIterates over all of the next classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < next_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tnext_classes[i].removeEventListener('touchend', AmplitudeHandlers.next );\n\t\t\t\tnext_classes[i].addEventListener('touchend', AmplitudeHandlers.next );\n\t\t\t}else{\n\t\t\t\tnext_classes[i].removeEventListener('click', AmplitudeHandlers.next );\n\t\t\t\tnext_classes[i].addEventListener('click', AmplitudeHandlers.next );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-prev\"\n\n\t\tBinds click and touchend events for amplitude prev buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPrev(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-prev\n\t\t*/\n\t\tvar prev_classes = document.getElementsByClassName(\"amplitude-prev\");\n\n\t\t/*\n\t\t\tIterates over all of the prev classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < prev_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tprev_classes[i].removeEventListener('touchend', AmplitudeHandlers.prev );\n\t\t\t\tprev_classes[i].addEventListener('touchend', AmplitudeHandlers.prev );\n\t\t\t}else{\n\t\t\t\tprev_classes[i].removeEventListener('click', AmplitudeHandlers.prev );\n\t\t\t\tprev_classes[i].addEventListener('click', AmplitudeHandlers.prev );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-shuffle\"\n\n\t\tBinds click and touchend events for amplitude shuffle buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindShuffle(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-shuffle\n\t\t*/\n\t\tvar shuffle_classes = document.getElementsByClassName(\"amplitude-shuffle\");\n\n\t\t/*\n\t\t\tIterates over all of the shuffle classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < shuffle_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tSince we are re-binding everything we remove any classes that signify\n\t\t\t\ta state of the shuffle control.\n\t\t\t*/\n\t\t\tshuffle_classes[i].classList.remove('amplitude-shuffle-on');\n\t\t\tshuffle_classes[i].classList.add('amplitude-shuffle-off');\n\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tshuffle_classes[i].removeEventListener('touchend', AmplitudeHandlers.shuffle );\n\t\t\t\tshuffle_classes[i].addEventListener('touchend', AmplitudeHandlers.shuffle );\n\t\t\t}else{\n\t\t\t\tshuffle_classes[i].removeEventListener('click', AmplitudeHandlers.shuffle );\n\t\t\t\tshuffle_classes[i].addEventListener('click', AmplitudeHandlers.shuffle );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-repeat\"\n\n\t\tBinds click and touchend events for amplitude repeat buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindRepeat(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-repeat\n\t\t*/\n\t\tvar repeat_classes = document.getElementsByClassName(\"amplitude-repeat\");\n\n\t\t/*\n\t\t\tIterates over all of the repeat classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < repeat_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tSince we are re-binding everything we remove any classes that signify\n\t\t\t\ta state of the repeat control.\n\t\t\t*/\n\t\t\trepeat_classes[i].classList.remove('amplitude-repeat-on');\n\t\t\trepeat_classes[i].classList.add('amplitude-repeat-off');\n\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\trepeat_classes[i].removeEventListener('touchend', AmplitudeHandlers.repeat );\n\t\t\t\trepeat_classes[i].addEventListener('touchend', AmplitudeHandlers.repeat );\n\t\t\t}else{\n\t\t\t\trepeat_classes[i].removeEventListener('click', AmplitudeHandlers.repeat );\n\t\t\t\trepeat_classes[i].addEventListener('click', AmplitudeHandlers.repeat );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-playback-speed\"\n\n\t\tBinds click and touchend events for amplitude playback speed buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPlaybackSpeed(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-playback-speed\n\t\t*/\n\t\tvar playback_speed_classes = document.getElementsByClassName(\"amplitude-playback-speed\");\n\n\t\t/*\n\t\t\tIterates over all of the playback speed classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < playback_speed_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tplayback_speed_classes[i].removeEventListener('touchend', AmplitudeHandlers.playbackSpeed );\n\t\t\t\tplayback_speed_classes[i].addEventListener('touchend', AmplitudeHandlers.playbackSpeed );\n\t\t\t}else{\n\t\t\t\tplayback_speed_classes[i].removeEventListener('click', AmplitudeHandlers.playbackSpeed );\n\t\t\t\tplayback_speed_classes[i].addEventListener('click', AmplitudeHandlers.playbackSpeed );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-skip-to\"\n\n\t\tBinds click and touchend events for amplitude skip to buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindSkipTo(){\n\t\t/*\n\t\t\tGets all of the skip to elements with the class 'amplitude-skip-to'\n\t\t*/\n\t\tvar skipToClasses = document.getElementsByClassName(\"amplitude-skip-to\");\n\n\t\t/*\n\t\t\tIterates over all of the skip to classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it's a click.\n\t\t*/\n\t\tfor( var i = 0; i < skipToClasses.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tskipToClasses[i].removeEventListener('touchend', AmplitudeHandlers.skipTo );\n\t\t\t\tskipToClasses[i].addEventListener('touchend', AmplitudeHandlers.skipTo );\n\t\t\t}else{\n\t\t\t\tskipToClasses[i].removeEventListener('click', AmplitudeHandlers.skipTo );\n\t\t\t\tskipToClasses[i].addEventListener('click', AmplitudeHandlers.skipTo );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tinitializeEvents: initializeEvents\n\t}\n})();\n\nexport default AmplitudeEvents\n\n\n\n// WEBPACK FOOTER //\n// ./src/events/events.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the Amplitude Visual Sync module\n * @module visual/AmplitudeVisualSync\n */\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * Imports the Amplitude Core module\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * Imports the Amplitude Core Helpers module\n * @module core/AmplitudeCoreHelpers\n */\nimport AmplitudeCoreHelpers from '../core/helpers.js';\n\n/**\n * These methods help handle interactions whether it's computation or shuffling\n * songs.\n *\n * @module events/AmplitudeEventsHelpers\n */\nlet AmplitudeEventsHelpers = (function() {\n\t/**\n\t * Computes the current song time. Breaks down where the song is into\n\t * hours, minutes, seconds and formats it to be displayed to the user.\n\t *\n\t * @access public\n\t */\n\tfunction computeCurrentTimes(){\n\t\t/*\n\t\t\tInitialize the current time object that will be returned.\n\t\t*/\n\t\tlet currentTime = {};\n\n\t\t/*\n\t\t\tComputes the current seconds for the song.\n\t\t*/\n\t\tlet currentSeconds = ( Math.floor( config.active_song.currentTime % 60 ) < 10 ? '0' : '' ) +\n\t\t\t\t\t\t\t Math.floor( config.active_song.currentTime % 60 );\n\n\t\t/*\n\t\t\tComputes the current minutes for the song.\n\t\t*/\n\t\tlet currentMinutes = Math.floor( config.active_song.currentTime / 60 );\n\n\t\t/*\n\t\t\tInitialize the current hours variable.\n\t\t*/\n\t\tlet currentHours = '00';\n\n\t\t/*\n\t\t\tIf the current minutes is less than 10, we add a leading 0.\n\t\t*/\n\t\tif( currentMinutes < 10 ){\n\t\t\tcurrentMinutes = '0'+currentMinutes;\n\t\t}\n\n\t\t/*\n\t\t\tIf the user is more than 60 minutes into the song, then\n\t\t\twe extract the hours.\n\t\t*/\n\t\tif( currentMinutes >= 60 ){\n\t\t\tcurrentHours \t\t= Math.floor( currentMinutes / 60 );\n\t\t\tcurrentMinutes \t\t= currentMinutes % 60;\n\n\t\t\t/*\n\t\t\t\tIf the user is less than 10 minutes in, we append the\n\t\t\t\tadditional 0 to the minutes.\n\t\t\t*/\n\t\t\tif( currentMinutes < 10 ){\n\t\t\t\tcurrentMinutes = '0'+currentMinutes;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tBuild a clean current time object and send back the appropriate information.\n\t\t*/\n\t\tcurrentTime.seconds = currentSeconds;\n\t\tcurrentTime.minutes = currentMinutes;\n\t\tcurrentTime.hours \t= currentHours;\n\n\t\treturn currentTime;\n\t}\n\n\t/**\n\t * Computes the current song duration. Breaks down where the song is into\n\t * hours, minutes, seconds and formats it to be displayed to the user.\n\t *\n\t * @access public\n\t */\n\tfunction computeSongDuration(){\n\t\t/*\n\t\t\tInitialize the song duration object that will be returned.\n\t\t*/\n\t\tlet songDuration = {};\n\n\t\t/*\n\t\t\tComputes the duration of the song's seconds.\n\t\t*/\n\t\tlet songDurationSeconds = ( Math.floor( config.active_song.duration % 60 ) < 10 ? '0' : '' ) +\n\t\t\t\t\t\t\t\t\t \t\tMath.floor( config.active_song.duration % 60 );\n\n\t\t/*\n\t\t\tComputes the duration of the song's minutes.\n\t\t*/\n\t\tlet songDurationMinutes = Math.floor( config.active_song.duration / 60 );\n\n\t\t/*\n\t\t\tInitialize the hours duration variable.\n\t\t*/\n\t\tvar songDurationHours = '0';\n\n\t\t/*\n\t\t\tIf the song duration minutes is less than 10, we add a leading 0.\n\t\t*/\n\t\tif( songDurationMinutes < 10 ){\n\t\t\tsongDurationMinutes = '0'+songDurationMinutes;\n\t\t}\n\n\t\t/*\n\t\t\tIf there is more than 60 minutes in the song, then we\n\t\t\textract the hours.\n\t\t*/\n\t\tif( songDurationMinutes >= 60 ){\n\t\t\tsongDurationHours \t\t= Math.floor( songDurationMinutes / 60 );\n\t\t\tsongDurationMinutes \t= songDurationMinutes % 60;\n\n\t\t\t/*\n\t\t\t\tIf the song duration minutes is less than 10 we append\n\t\t\t\tthe additional 0.\n\t\t\t*/\n\t\t\tif( songDurationMinutes < 10 ){\n\t\t\t\tsongDurationMinutes = '0'+songDurationMinutes;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tBuild a clean song duration object and send back the appropriate information.\n\t\t*/\n\t\tsongDuration.seconds \t= songDurationSeconds;\n\t\tsongDuration.minutes \t= songDurationMinutes;\n\t\tsongDuration.hours \t\t= songDurationHours;\n\n\t\treturn songDuration;\n\t}\n\n\t/**\n\t * Computes the song completion percentage.\n\t *\n\t * @access public\n\t */\n\tfunction computeSongCompletionPercentage(){\n\t\treturn ( config.active_song.currentTime / config.active_song.duration ) * 100;\n\t}\n\n\t/**\n\t * Sets the current song's playback speed\n\t *\n\t * @access public\n\t * @param {number} speed \t- The float with a base of 1 representing the speed\n\t *\n\t */\n\tfunction setPlaybackSpeed( speed ){\n\t\tAmplitudeCore.setPlaybackSpeed( speed );\n\t}\n\n\t/**\n\t * Sets the state of the repeat for the current song.\n\t *\n\t * @access public\n\t * @param {boolean} repeat - A boolean representing whether the repeat should be on or off\n\t * @param {string} playlist - The key of the playlist for repeating\n\t */\n\tfunction setRepeat( repeat, playlist ){\n\t\t/*\n\t\t If the playlist is null, then we are dealing with the global\n\t\t repeat status.\n\t\t*/\n\t\tif( playlist == null ){\n\t\t\t/*\n\t\t\t\tSet the global repeat to be toggled\n\t\t\t*/\n\t\t\tconfig.repeat = repeat;\n\n\t\t\t/*\n\t\t\t\tVisually sync repeat\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncRepeat();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tSet the playlist repeat to be toggled.\n\t\t\t*/\n\t\t\tconfig.repeat_statuses[playlist] = repeat;\n\n\t\t\t/*\n\t\t\t\tVisually sync playlist repeat\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncRepeatPlaylist( playlist );\n\t\t}\n\n\n/** When song ends and in playlis mode and done with playlist check repeat **/\n\n\n\t}\n\n\n\t/**\n\t * Sets the state of the repeat song\n\t *\n\t * @access public\n\t * @param {boolean} repeat - A boolean representing whether the repeat shoudl be on or off for the song.\n\t */\n\t function setRepeatSong( repeat ){\n\t\t config.repeat_song = repeat;\n\t }\n\n\t/**\n\t * Sets the main play pause buttons to the current state of the song.\n\t *\n\t * @access public\n\t */\n\tfunction setMainPlayPause(){\n\t\t/*\n\t\t\tDetermines what action we should take based on the\n\t\t\tstate of the song.\n\t\t*/\n\t\tif( config.active_song.paused ){\n\t\t\t/*\n\t\t\t\tThe song was paused so we sync visually for the song\n\t\t\t\tthat is playing and we play the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of playing.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\tto be paused and we pause the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of paused.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t/*\n\t\t\t\tPause the song\n\t\t\t*/\n\t\t\tAmplitudeCore.pause();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the playlist main play pause buttons to the current state of the song.\n\t *\n\t * @access public\n\t * @param {string} playlist The playlist the main play pause button controls\n\t */\n\tfunction setPlaylistPlayPause( playlist ){\n\t\t/*\n\t\t\tThe only thing that can change when you click a playlist\n\t\t\tplay pause is the playlist. Main play pauses have no change\n\t\t\tin song, song play pauses can change playlist and song.\n\t\t*/\n\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\t\t\t/*\n\t\t\t\tPlay first song in the playlist since we just\n\t\t\t\tswitched playlists, we start from the first song.\n\n\t\t\t\tIf the user has shuffle on for the playlist, then\n\t\t\t\twe go from the first song in the shuffle playlist array.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[playlist] ){\n\t\t\t\tAmplitudeCoreHelpers.changeSong( config.shuffled_playlists[playlist][0].original_index );\n\t\t\t}else{\n\t\t\t\tAmplitudeCoreHelpers.changeSong( config.playlists[playlist][0] );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDetermines what action we should take based on the\n\t\t\tstate of the song.\n\t\t*/\n\t\tif( config.active_song.paused ){\n\t\t\t/*\n\t\t\t\tThe song was paused so we sync visually for the song\n\t\t\t\tthat is playing and we play the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of playing.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\tto be paused and we pause the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of paused.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t/*\n\t\t\t\tPause the song\n\t\t\t*/\n\t\t\tAmplitudeCore.pause();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the song play pause buttons to the current state of the song.\n\t *\n\t * @access public\n\t * @param {string} playlist The playlist the song is a part of\n\t * @param {number} songIndex The index of the song being played/paused\n\t *\n\t */\n\tfunction setSongPlayPause( playlist, songIndex ){\n\t\t/*\n\t\t\tThere can be multiple playlists on the page and there can be\n\t\t\tmultiple songs on the page AND there can be songs in multiple\n\t\t\tplaylists, so we have some checking to do.\n\t\t*/\n\n\t\t/*\n\t\t\tCheck to see if the playlist has changed. If it has,\n\t\t\tset the active playlist.\n\t\t*/\n\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\t\t\t/*\n\t\t\t\tIf there's a new playlist then we reset the\n\t\t\t\tsong since the song could be in 2 playlists,\n\t\t\t\tbut the user selects another playlist.\n\t\t\t*/\n\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t}\n\n\t\t/*\n\t\t\tCheck to see if the song has changed. If it has,\n\t\t\tset the active song. If it was in a playlist, the\n\t\t\tsong wouldn't change here, since we already set the\n\t\t\tsong when we checked for a playlist.\n\t\t*/\n\t\tif( AmplitudeCoreHelpers.checkNewSong( songIndex ) ){\n\t\t\t/*\n\t\t\t\tThe song selected is different, so we change the\n\t\t\t\tsong.\n\t\t\t*/\n\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t}\n\n\t\t/*\n\t\t\tDetermines what action we should take based on the\n\t\t\tstate of the song.\n\t\t*/\n\t\tif( config.active_song.paused ){\n\t\t\t/*\n\t\t\t\tThe song was paused so we sync visually for the song\n\t\t\t\tthat is playing and we play the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of playing.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\tto be paused and we pause the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of paused.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t/*\n\t\t\t\tPause the song\n\t\t\t*/\n\t\t\tAmplitudeCore.pause();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the shuffle state for a playlist\n\t *\n\t * @access public\n\t * @param {string} playlist - The playlist being shuffled\n\t */\n\tfunction setShuffle( playlist ){\n\t\t/*\n\t\t\tIf the playlist is null, then we are dealing with the global\n\t\t\tshuffle status.\n\t\t*/\n\t\tif( playlist == null ){\n\t\t\t/*\n\t\t\t\tIf shuffle is on, we toggle it off. If shuffle is off, we\n\t\t\t\ttoggle on.\n\t\t\t*/\n\t\t\tif( config.shuffle_on ){\n\t\t\t\tconfig.shuffle_on \t= false;\n\t\t\t\tconfig.shuffle_list = {};\n\t\t\t}else{\n\t\t\t\tconfig.shuffle_on = true;\n\t\t\t\tAmplitudeCoreHelpers.shuffleSongs();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tVisually sync the shuffle statuses\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncShuffle( config.shuffle_on );\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the playlist shuffled is on, we toggle it off. If the\n\t\t\t\tplaylist shuffled is off, we toggle it on.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[playlist] ){\n\t\t\t\tconfig.shuffled_statuses[playlist] = false;\n\t\t\t\tconfig.shuffled_playlists[playlist] = [];\n\t\t\t}else{\n\t\t\t\tconfig.shuffled_statuses[playlist] = true;\n\t\t\t\tAmplitudeCoreHelpers.shufflePlaylistSongs( playlist );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tVisually sync the playlist shuffle statuses.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistShuffle( config.shuffled_statuses[playlist], playlist );\n\t\t}\n\t}\n\n\t/**\n\t * Sets the next song when next is clicked\n\t *\n\t * @access public\n\t * @param {boolean} [songEnded=false] If the song ended, this is set to true\n\t * so we take into effect the repeat setting.\n\t*/\n\tfunction setNext( songEnded = false ){\n\t\t/*\n\t\t\tInitializes the next index variable. This will be the\n\t\t\tindex of the song that is next.\n\t\t*/\n\t\tlet nextIndex = 0;\n /*\n Ensure we don't loop in the playlist if config.repeat is not true\n */\n\t\tlet endOfList = false;\n\n\t\tif( config.repeat_song ){\n\t\t\t/*\n\t\t\t\tIf the playlist is shuffled, get the now playing index.\n\t\t\t*/\n\t\t\tif( config.shuffle_on ){\n\t\t\t\tnextIndex = config.shuffle_active_index;\n\t\t\t}else{\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}else{\n\n\t\t\t/*\n\t\t\t\tIf the shuffle is on, we use the shuffled list of\n\t\t\t\tsongs to determine our next song.\n\t\t\t*/\n\t\t\tif( config.shuffle_on ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active shuffle index + 1 is less than the length, then\n\t\t\t\t\twe use the next shuffle otherwise we go to the beginning\n\t\t\t\t\tof the shuffle list.\n\t\t\t\t*/\n\t\t\t\tif( ( parseInt( config.shuffle_active_index ) + 1 ) < config.shuffle_list.length ){\n\t\t\t\t\tconfig.shuffle_active_index = parseInt( config.shuffle_active_index ) + 1;\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the next index to be the index of the song in the shuffle list.\n\t\t\t\t\t*/\n\t\t\t\t\tnextIndex = config.shuffle_list[ parseInt( config.shuffle_active_index ) ].original_index;\n\t\t\t\t}else{\n\t\t\t\t\tconfig.shuffle_active_index = 0;\n\t\t\t\t\tnextIndex = 0;\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active index + 1 is less than the length of the songs, then\n\t\t\t\t\twe use the next song otherwise we go to the beginning of the\n\t\t\t\t\tsong list.\n\t\t\t\t*/\n\t\t\t\tif( ( parseInt( config.active_index ) + 1 ) < config.songs.length ){\n\t\t\t\t\tconfig.active_index = parseInt( config.active_index ) + 1;\n\t\t\t\t}else{\n\t\t\t\t\tconfig.active_index = 0;\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t\tSets the next index.\n\t\t\t\t*/\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChange the song to the index we need.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( nextIndex );\n\n\n\t\t/*\n\t\t\tIf it's the end of the list and repeat is not on, do nothing.\n\t\t*/\n\t\tif( endOfList && !config.repeat ){\n\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the song has ended and repeat is on, play the song.\n\t\t\t*/\n\t if( !( songEnded && !config.repeat && endOfList ) ){\n\t \tAmplitudeCore.play();\n\t }\n\t\t}\n\n /*\n \tSyncs the main play pause button, playlist play pause button and\n \tsong play pause.\n */\n\t\tAmplitudeVisualSync.syncMainPlayPause( );\n\t\tAmplitudeVisualSync.syncSongPlayPause( null, nextIndex);\n\n /*\n \tCall after next callback\n */\n AmplitudeCoreHelpers.runCallback('after_next');\n\n\t\t/*\n\t\t\tIf we are repeating the song, call the song repeated callback\n\t\t*/\n\t\tif( config.repeat_song ){\n\t\t\tAmplitudeCoreHelpers.runCallback('song_repeated');\n\t\t}\n\t}\n\n\t/**\n\t * Sets the next song in a playlist\n\t *\n\t * @param {string} playlist - The playlist being shuffled\n\t * @param {boolean} [songEnded=false] - If the song ended, this is set to true\n\t * so we take into effect the repeat setting.\n\t */\n\tfunction setNextPlaylist( playlist, songEnded = false ){\n\t\t/*\n\t\t\tInitializes the next index\n\t\t*/\n\t\tlet nextIndex = 0;\n\n /*\n Used to determine whether the playlist looped over\n If it did, only play if repeat is allowed, end otherwise\n @TODO: Different settings for song loop, in-playlist loop and global loop\n */\n\t\tlet endOfList = false;\n\n\t\t/*\n\t\t\tIf we are repeating the song, then we just start the song over.\n\t\t*/\n\n\t\tif( config.repeat_song ){\n\t\t\t/*\n\t\t\t\tIf the playlist is shuffled, get the now playing index.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[ playlist ] ){\n\t\t\t\tnextIndex = config.shuffled_playlists[ playlist ][ config.shuffled_active_indexes[ playlist ] ].original_index;\n\t\t\t}else{\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the playlist is shuffled we get the next index of the playlist.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[ playlist ] ){\n\t\t\t\t/*\n\t\t\t\t\tGets the shuffled playlist's active song index.\n\t\t\t\t*/\n\t\t\t\tlet shuffledPlaylistActiveSongIndex = parseInt( config.shuffled_active_indexes[ playlist ] );\n\n\t\t\t\t/*\n\t\t\t\t\tIf the index + 1 is less than the length of the playlist, we increment\n\t\t\t\t\tthe next index otherwise we take the first index of 0.\n\t\t\t\t*/\n\t\t\t\tif( shuffledPlaylistActiveSongIndex + 1 < config.shuffled_playlists[ playlist ].length ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the shuffled playlist active song index.\n\t\t\t\t\t*/\n\t\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = shuffledPlaylistActiveSongIndex + 1;\n\t\t\t\t\t/*\n\t\t\t\t\t\tGet the index of the song that we will be switching to.\n\t\t\t\t\t*/\n\t\t\t\t\tnextIndex = config.shuffled_playlists[ playlist ][ config.shuffled_active_indexes[ playlist ] ].original_index;\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets the active shuffled playlist active index to 0 and gets the original index of\n\t\t\t\t\t\tthe song at the shuffled index of 0.\n\t\t\t\t\t*/\n\t\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = 0;\n\t\t\t\t\tnextIndex = config.shuffled_playlists[ playlist ][0].original_index;\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the index of the active song within the scope\n\t\t\t\t\tof the playlist.\n\t\t\t\t*/\n\t\t\t\tlet playlistActiveSongIndex = config.playlists[ playlist ].indexOf( parseInt( config.active_index ) );\n\n\t\t\t\t/*\n\t\t\t\t\tChecks to see if the next index is still less than the length of the playlist.\n\t\t\t\t\tIf it is, use the next index othwerwise get the first song in the playlist.\n\t\t\t\t*/\n\t\t\t\tif( playlistActiveSongIndex + 1 < config.playlists[ playlist ].length ){\n\t\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][ playlistActiveSongIndex + 1 ] );\n\t\t\t\t}else{\n\t\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][0] );\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t\tSets the next inex to the active index in the config.\n\t\t\t\t*/\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song playing.\n\t\t*/\n\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChanges the song to the next song in the playlist.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( nextIndex );\n\n\t\t/*\n\t\t\tIf it's the end of the song in the playlist, and repeat for\n\t\t\tthe playlist is not on, do nothing.\n\t\t*/\n\t\tif( endOfList && !config.repeat_statuses[playlist] ){\n\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the song has ended and repeat is on, play the song.\n\t\t\t*/\n\t if( !( songEnded && !config.repeat_statuses[playlist] && endOfList ) ){\n\t\t\t\tAmplitudeCore.play();\n\t\t\t}\n\t\t}\n\n\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\n\n /*\n \tSyncs the main play pause button, playlist play pause button and\n \tsong play pause.\n */\n\t\tAmplitudeVisualSync.syncMainPlayPause( );\n\t\tAmplitudeVisualSync.syncPlaylistPlayPause(playlist);\n\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, nextIndex);\n\n /*\n \tCall after next callback\n */\n AmplitudeCoreHelpers.runCallback('after_next');\n\n\t\t/*\n\t\t\tIf we are repeating the song, call the song repeated callback\n\t\t*/\n\t\tif( config.repeat_song ){\n\t\t\tAmplitudeCoreHelpers.runCallback('song_repeated');\n\t\t}\n\t}\n\n\t/**\n\t * Sets the previous song\n\t * @access public\n\t *\n\t/*--------------------------------------------------------------------------\n\t\tSets the previous song\n\t--------------------------------------------------------------------------*/\n\tfunction setPrev(){\n\t\t/*\n\t\t\tInitializes the prev index variable. This will be the\n\t\t\tindex of the song that is next.\n\t\t*/\n\t\tlet prevIndex = 0;\n\n\t\t/*\n\t\t\tIf the shuffle is on for the individual songs, we get the previous\n\t\t\tsong.\n\t\t*/\n\t\tif( config.shuffle_on ){\n\t\t\t/*\n\t\t\t\tIf the previous index is greater than or equal to 0, we use the active\n\t\t\t\tindex - 1.\n\t\t\t*/\n\t\t\tif( parseInt( config.shuffle_active_index ) - 1 >= 0 ){\n\t\t\t\t/*\n\t\t\t\t\tSets the new active to be 1 less than the current active index.\n\t\t\t\t*/\n\t\t\t\tconfig.shuffle_active_index = parseInt( config.shuffle_active_index ) - 1;\n\n\t\t\t\t/*\n\t\t\t\t\tGets the index of the song in the song array for the new index.\n\t\t\t\t*/\n\t\t\t\tprevIndex = config.shuffle_list[ parseInt( config.shuffle_active_index ) ].original_index;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the active index and previous index.\n\t\t\t\t*/\n\t\t\t\tconfig.shuffle_active_index = config.shuffle_list.length - 1;\n\t\t\t\tprevIndex = config.shuffle_list[ parseInt( config.shuffle_list.length ) - 1 ].original_index;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the active index - 1 is greater than or equal to 0, we subtract 1 from the\n\t\t\t\tactive index otherwise we set the active index to the end of the songs array index.\n\t\t\t*/\n\t\t\tif( parseInt( config.active_index ) - 1 >= 0 ){\n\t\t\t\tconfig.active_index = parseInt( config.active_index ) - 1;\n\t\t\t}else{\n\t\t\t\tconfig.active_index = config.songs.length - 1;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSet the previous index.\n\t\t\t*/\n\t\t\tprevIndex = config.active_index;\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChange the song to the index we need.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( prevIndex );\n\n\t\t/*\n\t\t\tPlay the next song.\n\t\t*/\n\t\tAmplitudeCore.play();\n\n\t\t/*\n\t\t\tSync the play/pause buttons to the current state of the player.\n\t\t*/\n\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\tAmplitudeVisualSync.syncSongPlayPause( null, prevIndex, 'playing' );\n\n\t\t/*\n\t\t\tCall after prev callback\n\t\t*/\n\t\tAmplitudeCoreHelpers.runCallback('after_prev');\n\t}\n\n\t/**\n\t * Sets the previous song in a playlist\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the previous for.\n\t */\n\tfunction setPrevPlaylist( playlist ){\n\t\t/*\n\t\t\tInitializes the prev index variable. This will be the\n\t\t\tindex of the song that is next.\n\t\t*/\n\t\tlet prevIndex = 0;\n\n\t\t/*\n\t\t\tIf the shuffle is on for the playlist, we get the previous\n\t\t\tsong.\n\t\t*/\n\t\tif( config.shuffled_statuses[ playlist ] ){\n\t\t\t/*\n\t\t\t\tGets the active song index for the shuffled playlist\n\t\t\t*/\n\t\t\tlet shuffledPlaylistActiveSongIndex = parseInt( config.shuffled_active_indexes[ playlist ] );\n\n\t\t\t/*\n\t\t\t\tIf the shuffled song active index is greater than or equal to 0,\n\t\t\t\twe use the active index - 1.\n\t\t\t*/\n\t\t\tif( shuffledPlaylistActiveSongIndex - 1 >= 0 ){\n\t\t\t\t/*\n\t\t\t\t\tSets the active index to the active song index - 1\n\t\t\t\t*/\n\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = shuffledPlaylistActiveSongIndex - 1;\n\n\t\t\t\t/*\n\t\t\t\t\tGets the index of the song in the song array for the new index.\n\t\t\t\t*/\n\t\t\t\tprevIndex = config.shuffled_playlists[ playlist ][ config.shuffled_active_indexes[ playlist ] ].original_index;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the active index and previous index.\n\t\t\t\t*/\n\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = config.shuffled_playlists[ playlist ].length - 1;\n\t\t\t\tprevIndex = config.shuffled_playlists[ playlist ][ config.shuffled_playlists[ playlist ].length - 1 ].original_index;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tGets the active song index for the playlist\n\t\t\t*/\n\t\t\tlet playlistActiveSongIndex = config.playlists[ playlist ].indexOf( parseInt( config.active_index ) );\n\n\t\t\t/*\n\t\t\t\tIf the active song index in the playlist - 1 is greater than\n\t\t\t\tor equal to 0, then we use the active song index - 1.\n\t\t\t*/\n\t\t\tif( playlistActiveSongIndex - 1 >= 0 ){\n\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][ playlistActiveSongIndex - 1 ] );\n\t\t\t}else{\n\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][ config.playlists[ playlist ].length - 1 ] );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSet the previous index to the active index for use later.\n\t\t\t*/\n\t\t\tprevIndex = config.active_index;\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChanges the song to the prev song in the playlist.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( prevIndex );\n\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\t\t/*\n\t\t\tPlays the song\n\t\t*/\n\t\tAmplitudeCore.play();\n\n\t\t/*\n\t\t\tSyncs the main play pause button, playlist play pause button and\n\t\t\tsong play pause.\n\t\t*/\n\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\tAmplitudeVisualSync.syncPlaylistPlayPause( playlist, 'playing' );\n\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, prevIndex, 'playing' );\n\n\t\t/*\n\t\t\tCall after prev callback\n\t\t*/\n\t\tAmplitudeCoreHelpers.runCallback('after_prev');\n\t}\n\n\t/**\n\t * Runs an event on key down\n\t *\n\t * @access public\n\t * @param {number} key \t- The key code the event is bound to.\n\t */\n\tfunction runKeyEvent( key ){\n\t\t/*\n\t\t\tChecks to see if the user bound an event to the code pressed.\n\t\t*/\n\t\tif( config.bindings[key] != undefined ){\n\t\t\t/*\n\t\t\t\tDetermine which event should be run if bound.\n\t\t\t*/\n\t\t\tswitch( config.bindings[key] ){\n\t\t\t\t/*\n\t\t\t\t\tFires a play pause event.\n\t\t\t\t*/\n\t\t\t\tcase 'play_pause':\n\t\t\t\t\tsetSongPlayPause( config.active_playlist, config.active_index );\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a next event.\n\t\t\t\t*/\n\t\t\t\tcase 'next':\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the current state of the player\n\t\t\t\t\t\tis in playlist mode or not playlist mode.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\t\tsetNext();\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsetNextPlaylist( config.active_playlist );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a previous event.\n\t\t\t\t*/\n\t\t\t\tcase 'prev':\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the current playlist has been set\n\t\t\t\t\t\tor null and set the previous song.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\t\tAmplitudeEventsHelpers.setPrev();\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( config.active_playlist );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a stop event.\n\t\t\t\t*/\n\t\t\t\tcase 'stop':\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets all of the play/pause buttons to pause\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tStops the active song.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeCore.stop();\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a shuffle event.\n\t\t\t\t*/\n\t\t\t\tcase 'shuffle':\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the current playlist has been set\n\t\t\t\t\t\tor null and set the previous song.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\t\tAmplitudesEventHelpers.setShuffle( null );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeEvenstHelpers.setShuffle( config.active_playlist );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a repeat event.\n\t\t\t\t*/\n\t\t\t\tcase 'repeat':\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets repeat to the opposite of what it was set to\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat );\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tVisually sync repeat\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncRepeat();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t\tReturn the publically scoped functions\n\t*/\n\treturn {\n\t\tcomputeCurrentTimes: computeCurrentTimes,\n\t\tcomputeSongDuration: computeSongDuration,\n\t\tcomputeSongCompletionPercentage: computeSongCompletionPercentage,\n\t\tsetPlaybackSpeed: setPlaybackSpeed,\n\t\tsetRepeat: setRepeat,\n\t\tsetRepeatSong: setRepeatSong,\n\t\tsetMainPlayPause: setMainPlayPause,\n\t\tsetPlaylistPlayPause: setPlaylistPlayPause,\n\t\tsetSongPlayPause: setSongPlayPause,\n\t\tsetShuffle: setShuffle,\n\t\tsetNext: setNext,\n\t\tsetNextPlaylist: setNextPlaylist,\n\t\tsetPrev: setPrev,\n\t\tsetPrevPlaylist: setPrevPlaylist,\n\t\trunKeyEvent: runKeyEvent\n\t}\n})();\n\nexport default AmplitudeEventsHelpers\n\n\n\n// WEBPACK FOOTER //\n// ./src/events/helpers.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * AmplitudeJS Core Module\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * AmplitudeJS Core Helpers\n * @module core/AmplitudeHelpers\n */\nimport AmplitudeHelpers from '../core/helpers.js';\n\n/**\n * AmplitudeJS Events\n * @module events/AmplitudeEvents\n */\nimport AmplitudeEvents from '../events/events.js';\n\n/**\n * AmplitudeJS Soundcloud\n * @module soundcloud/AmplitudeSoundcloud\n */\nimport AmplitudeSoundcloud from '../soundcloud/soundcloud.js';\n\n/**\n * AmplitudeJS Visual Sync\n * @module visual/AmplitudeVisualSync\n*/\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * AmplitudeJS Initializer Module. Helps with the handling of all of the\n * initialization for AmplitudeJS.\n *\n * @module init/AmplitudeInitializer\n */\nlet AmplitudeInitializer = (function () {\n\n\t/**\n * The main init function. The user will call this through\n\t * Amplitude.init({}) and pass in their settings.\n\t *\n\t * Public Accessor: Amplitude.init( user_config_json )\n\t * @access public\n * @param {object} userConfig - A JSON object of user defined values that help configure and initialize AmplitudeJS.\n */\n\tfunction initialize( userConfig ){\n\t\tlet ready = false;\n\n\t\t/*\n\t\t\tReset the config on init so we have a clean slate. This is if the\n\t\t\tuser has to re-init.\n\t\t*/\n\t\tAmplitudeHelpers.resetConfig();\n\n\t\t/*\n\t\t\tInitialize event handlers on init. This will clear any old\n\t\t\tevent handlers on the amplitude element and re-bind what is\n\t\t\tnecessary.\n\t\t*/\n\t\tAmplitudeEvents.initializeEvents();\n\n\t\t/*\n\t\t\tInitializes debugging right away so we can use it for the rest\n\t\t\tof the configuration.\n\t\t*/\n\t\tconfig.debug = ( userConfig.debug != undefined ? userConfig.debug : false );\n\n\t\t/*\n\t\t\tChecks to see if the user has songs defined.\n\t\t*/\n\t\tif( userConfig.songs ){\n\t\t\t/*\n\t\t\t\tChecks to see if the user has some songs in the songs array.\n\t\t\t*/\n\t\t\tif( userConfig.songs.length != 0 ){\n\t\t\t\t/*\n\t\t\t\t\tCopies over the user defined songs. and prepares\n\t\t\t\t\tAmplitude for the rest of the configuration.\n\t\t\t\t*/\n\t\t\t\tconfig.songs = userConfig.songs;\n\t\t\t\t/*\n\t\t\t\t\tFlag amplitude as ready.\n\t\t\t\t*/\n\t\t\t\tready = true;\n\t\t\t}else{\n\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'Please add some songs, to your songs object!' );\n\t\t\t}\n\t\t}else{\n\t\t\tAmplitudeHelpers.writeDebugMessage( 'Please provide a songs object for AmplitudeJS to run!' );\n\t\t}\n\n\t\t/**\n\t\t * Initializes the audio context. In this method it checks to see if the\n\t\t * user wants to use visualizations or not before proceeding.\n\t\t * @todo MAKE HANDLED BY AMPLITUDE FX.\n\t\t */\n\t\t//privateHelpInitializeAudioContext();\n\n\t\t/*\n\t\t\tChecks if the user has any playlists defined. If they do\n\t\t\twe have to initialize the functionality for the playlists.\n\t\t*/\n\t\tif( userConfig.playlists && countPlaylists( userConfig.playlists ) > 0 ){\n\t\t\t/*\n\t\t\t\tCopy the playlists over to Amplitude\n\t\t\t*/\n\t\t\tconfig.playlists = userConfig.playlists;\n\n\t\t\t/*\n\t\t\t\tInitialize default live settings\n\t\t\t*/\n\t\t\tinitializeDefaultLiveSettings();\n\n\t\t\t/*\n\t\t\t\tCheck to see if the user has valid song indexes in their playlist.\n\t\t\t*/\n\t\t\tcheckValidSongsInPlaylists();\n\n\t\t\t/*\n\t\t\t\tInitialize the shuffle status of the playlists.\n\t\t\t*/\n\t\t\tinitializePlaylistShuffleStatuses();\n\n\t\t\t/*\n\t\t\t\tInitialize the repeat status for the playlits.\n\t\t\t*/\n\t\t\tinitializePlaylistsRepeatStatuses();\n\n\t\t\t/*\n\t\t\t\tInitialize temporary place holders for shuffle lists.\n\t\t\t*/\n\t\t\tinitializePlaylistShuffleLists();\n\n\t\t\t/*\n\t\t\t\tInitializes the active shuffled indexes for shuffled playlists.\n\t\t\t*/\n\t\t\tinitializePlaylistShuffleIndexes();\n\n\t\t\t/*\n\t\t\t\tInitializes the first song in the playlist\n\t\t\t*/\n\t\t\tinitializeFirstSongInPlaylistMetaData();\n\t\t}\n\n\t\t/*\n\t\t\tWhen the preliminary config is ready, we are ready to proceed.\n\t\t*/\n\t\tif( ready ){\n\t\t\t/*\n\t\t\t\tCopies over the soundcloud information to the global config\n\t\t\t\twhich will determine where we go from there.\n\t\t\t*/\n\t\t\tconfig.soundcloud_client = ( userConfig.soundcloud_client != undefined ? userConfig.soundcloud_client : '' );\n\n\t\t\t/*\n\t\t\t\tChecks if we want to use the art loaded from soundcloud.\n\t\t\t*/\n\t\t\tconfig.soundcloud_use_art = ( userConfig.soundcloud_use_art != undefined ? userConfig.soundcloud_use_art : '' );\n\n\t\t\t/*\n\t\t\t\tIf the user provides a soundcloud client then we assume that\n\t\t\t\tthere are URLs in their songs that will reference SoundcCloud.\n\t\t\t\tWe then copy over the user config they provided to the\n\t\t\t\ttemp_user_config so we don't mess up the global or their configs\n\t\t\t\tand load the soundcloud information.\n\t\t\t*/\n\t\t\tlet tempUserConfig = {};\n\n\t\t\tif( config.soundcloud_client != '' ){\n\t\t\t\ttempUserConfig = userConfig;\n\n\t\t\t\t/*\n\t\t\t\t\tLoad up SoundCloud for use with AmplitudeJS.\n\t\t\t\t*/\n\t\t\t\tAmplitudeSoundcloud.loadSoundCloud( tempUserConfig );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tThe user is not using Soundcloud with Amplitude at this point\n\t\t\t\t\tso we just finish the configuration with the users's preferences.\n\t\t\t\t*/\n\t\t\t\tsetConfig( userConfig );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDebug out what was initialized with AmplitudeJS.\n\t\t*/\n\t\tAmplitudeHelpers.writeDebugMessage( 'Initialized With: ');\n\t\tAmplitudeHelpers.writeDebugMessage( config );\n\t}\n\n\t/**\n\t * Rebinds all of the elements in the display.\n\t *\n\t * Public Accessor: Amplitude.rebindDisplay()\n\t * @access public\n\t */\n\tfunction rebindDisplay(){\n\t\tAmplitudeEvents.initializeEvents();\n\t\tAmplitudeVisualSync.displaySongMetadata();\n\t}\n\n\t/**\n\t * Finishes the initalization of the config. Takes all of the user defined\n\t * parameters and makes sure they override the defaults. The important\n\t * config information is assigned in the publicInit() function.\n\t *\n\t * This function can be called from 2 different locations:\n\t * \t1. Right away on init after the important settings are defined.\n\t *\n\t * \t2. After all of the Soundcloud URLs are resolved properly and\n\t *\t \tsoundcloud is configured. We will need the proper URLs from Soundcloud\n\t * \t\tto stream through Amplitude so we get those right away before we\n\t * \t\tset the information and the active song\n\t *\n\t * @access public\n\t * @param {object} userConfig - A JSON object of user defined values that help configure and initialize AmplitudeJS.\n\t */\n\tfunction setConfig( userConfig ){\n\t\t/*\n\t\t\tCheck to see if the user entered a start song\n\t\t*/\n\t\tif( userConfig.start_song != undefined ){\n\t\t\t/*\n\t\t\t\tEnsure what has been entered is an integer.\n\t\t\t*/\n\t\t\tif( AmplitudeHelpers.isInt( userConfig.start_song ) ){\n\t\t\t\tAmplitudeHelpers.changeSong( userConfig.start_song );\n\t\t\t}else{\n\t\t\t\tAmplitudeHelpers.writeDebugMessage(\"You must enter an integer index for the start song.\");\n\t\t\t}\n\t\t}else{\n\t\t\tAmplitudeHelpers.changeSong( 0 );\n\t\t}\n\n\t\t/*\n\t\t\tInitialize a sh\n\t\t*/\n\t\tif( userConfig.shuffle_on != undefined && userConfig.shuffle_on ){\n\t\t\tconfig.shuffle_on = true;\n\t\t\tAmplitudeHelpers.shuffleSongs();\n\n\t\t\t/*\n\t\t\t\tVisually sync the shuffle statuses\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncShuffle( config.shuffle_on );\n\n\t\t\tAmplitudeHelpers.changeSong( config.shuffle_list[0].original_index );\n\t\t}\n\n\t\t/*\n\t\t\tAllows the user to set whether they want to continue to the next song\n\t\t\twhen the current song finishes or not. In any scenario that's not a playlist,\n\t\t\tcontining to the next song may not be desired.\n\t\t*/\n\t\tconfig.continue_next = ( userConfig.continue_next != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t userConfig.continue_next :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t true );\n\n\t\t/*\n\t\t\tIf the user defined a playback speed, we copy over their\n\t\t\tpreference here, otherwise we default to normal playback\n\t\t\tspeed of 1.0.\n\t\t*/\n\t\tconfig.playback_speed = ( userConfig.playback_speed != undefined ?\n\t\t\t\t\t\t\t\t \t\t\t\t\t\tuserConfig.playback_speed :\n\t\t\t\t\t\t\t\t \t\t\t\t\t\t1.0 );\n\n\t\t/*\n\t\t\tSets the audio playback speed.\n\t\t*/\n\t\tAmplitudeCore.setPlaybackSpeed( config.playback_speed );\n\n\t\t/*\n\t\t\tIf the user wants the song to be pre-loaded for instant\n\t\t\tplayback, they set it to true. By default it's set to just\n\t\t\tload the metadata.\n\t\t*/\n\t\tconfig.active_song.preload = ( userConfig.preload != undefined ?\n\t\t\t\t\t\t\t\t\t \t\t\t\t\t\t\t userConfig.preload :\n\t\t\t\t\t\t\t\t\t \t\t\t\t\t \t\t \"auto\" );\n\n\t\t/*\n\t\t\tInitializes the user defined callbacks. This should be a JSON\n\t\t\tobject that contains a key->value store of the callback name\n\t\t\tand the name of the function the user needs to call.\n\t\t*/\n\t\tconfig.callbacks = ( userConfig.callbacks != undefined ?\n\t\t\t\t\t\t\t \t\t\t\t\t userConfig.callbacks :\n\t\t\t\t\t\t\t \t\t\t\t \t {} );\n\n\t\t/*\n\t\t\tInitializes the user defined key bindings. This should be a JSON\n\t\t\tobject that contains a key->value store of the key event number\n\t\t\tpressed and the method to be run.\n\t\t*/\n\t\tconfig.bindings = ( userConfig.bindings != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\tuserConfig.bindings :\n\t\t\t\t\t\t\t\t\t\t\t\t{} );\n\n\t\t/*\n\t\t\tThe user can define a starting volume in a range of 0-100 with\n\t\t\t0 being muted and 100 being the loudest. After the config is set\n\t\t\tAmplitude sets the active song's volume to the volume defined\n\t\t\tby the user.\n\t\t*/\n\t\tconfig.volume = ( userConfig.volume != undefined ?\n\t\t\t \t\t\t \t\t\t\tuserConfig.volume :\n\t\t\t \t\t\t \t\t\t\t50 );\n\n\t\t/*\n\t\t\tThe user can set the volume increment and decrement values between 1 and 100\n\t\t\tfor when the volume up or down button is pressed. The default is an increase\n\t\t\tor decrease of 5.\n\t\t*/\n\t\tconfig.volume_increment = ( userConfig.volume_increment != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuserConfig.volume_increment :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t5 );\n\n\t\tconfig.volume_decrement = ( userConfig.volume_decrement != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuserConfig.volume_decrement :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t5 );\n\n\t\t/*\n\t\t\tSet the volume to what is defined in the config. The user can define this,\n\t\t\tso we should set it up that way.\n\t\t*/\n\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t/*\n\t\t\tSince the user can define a start volume, we want our volume\n\t\t\tsliders to sync with the user defined start value.\n\t\t*/\n\t\tAmplitudeVisualSync.syncVolumeSliders();\n\n\t\t/*\n\t\t\tIf the user defines default album art, this image will display if the active\n\t\t\tsong doesn't have album art defined.\n\t\t*/\n\t\tif( userConfig.default_album_art != undefined ){\n\t\t\tconfig.default_album_art = userConfig.default_album_art;\n\t\t}else{\n\t\t\tconfig.default_album_art = '';\n\t\t}\n\n\t\t/*\n\t\t\tSyncs all of the visual time elements to 00.\n\t\t*/\n\t\tAmplitudeVisualSync.resetTimes();\n\n\t\t/*\n\t\t\tSets all of the play pause buttons to pause.\n\t\t*/\n\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t/*\n\t\t\tSets the meta data for the songs automatically.\n\t\t*/\n\t\tAmplitudeVisualSync.syncSongsMetaData();\n\n\t\t/*\n\t\t\tIf the user has autoplay enabled, then begin playing the song. Everything should\n\t\t\tbe configured for this to be ready to play.\n\t\t*/\n\t\tif( userConfig.autoplay ){\n\t\t\t/*\n\t\t\t\tIf the user hasn't set a starting playlist, set it to null otherwise initialize to the\n\t\t\t\tstarting playlist selected by the user.\n\t\t\t*/\n\t\t\tif( userConfig.starting_playlist == '' ){\n\t\t\t\tconfig.active_playlist = null;\n\t\t\t}else{\n\t\t\t\tconfig.active_playlist = userConfig.starting_playlist;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSync the main and song play pause buttons.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, 0, 'playing' );\n\n\t\t\t/*\n\t\t\t\tStart playing the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}\n\n\t\t/*\n\t\t\tIf the user has selected a starting playlist, we need to set the starting playlist\n\t\t\tand sync the visuals\n\t\t*/\n\t\tif( userConfig.starting_playlist != undefined && userConfig.starting_playlist != '' ){\n\t\t\t/*\n\t\t\t\tSet the active playlist to the starting playlist by the user\n\t\t\t*/\n\t\t\tconfig.active_playlist = userConfig.starting_playlist;\n\n\t\t\t/*\n\t\t\t\tCheck if the user defined a song to start with in the playlist.\n\t\t\t*/\n\t\t\tif( userConfig.starting_playlist_song != undefined && userConfig.starting_playlist_song != '' ){\n\t\t\t\t/*\n\t\t\t\t\tEnsure the song is a valid index.\n\t\t\t\t*/\n\t\t\t\tif( typeof userConfig.playlists[ userConfig.starting_playlist ][ parseInt( userConfig.starting_playlist_song ) ] != undefined ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the player to the song defined by the user.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeHelpers.changeSong( userConfig.playlists[ userConfig.starting_playlist ][ parseInt( userConfig.starting_playlist_song ) ] );\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the player to the first song in the playlist\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeHelpers.changeSong( userConfig.playlists[ userConfig.starting_playlist ][0] );\n\t\t\t\t\t/*\n\t\t\t\t\t\tDebug that the song index doesn't exist\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'The index of '+userConfig.starting_playlist_song+' does not exist in the playlist '+userConfig.starting_playlist );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the player to the first song in the playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeHelpers.changeSong( userConfig.playlists[ userConfig.starting_playlist ][0] );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSync the main and song play pause buttons.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, 0, 'paused' );\n\t\t}\n\n\t\t/*\n\t\t\tRun after init callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_init');\n\t}\n\n\t/**\n\t * Counts the number of playlists the user has configured. This ensures\n\t * that the user has at least 1 playlist so we can validate the songs\n\t * defined in the playlist are correct and they didn't enter an invalid\n\t * ID.\n\t *\n\t * @access private\n\t * @param {object} playlists \t-\n\t */\n\tfunction countPlaylists( playlists ){\n\t\t/*\n\t\t\tInitialize the placeholders to iterate through the playlists\n\t\t\tand find out how many we have to account for.\n\t\t*/\n\t\tlet size = 0, key;\n\n\t\t/*\n\t\t\tIterate over playlists and if the user has the playlist defined,\n\t\t\tincrement the size of playlists.\n\t\t*/\n\t\tfor ( key in playlists ) {\n\t\t\tif( playlists.hasOwnProperty( key) ){\n\t\t\t\tsize++;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDebug how many playlists are in the config.\n\t\t*/\n\t\tAmplitudeHelpers.writeDebugMessage( 'You have '+size+' playlist(s) in your config' );\n\n\t\t/*\n\t\t\tReturn the number of playlists in the config.\n\t\t*/\n\t\treturn size;\n\t}\n\n\t/**\n\t* Ensures the indexes in the playlists are valid indexes. The song has\n\t* to exist in the Amplitude config to be played correctly.\n\t*\n\t* @access private\n\t*/\n\tfunction checkValidSongsInPlaylists(){\n\t\t/*\n\t\t\tIterate over all of the config's playlists\n\t\t*/\n\t\tfor( let key in config.playlists ){\n\t\t\t/*\n\t\t\t\tChecks if the playlist key is accurate.\n\t\t\t*/\n\t\t\tif( config.playlists.hasOwnProperty( key) ){\n\t\t\t\t/*\n\t\t\t\t\tChecks if the playlist has songs.\n\t\t\t\t*/\n\t\t\t\tif( config.playlists[key].songs ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tIterate over all of the songs in the playlist\n\t\t\t\t\t*/\n\t\t\t\t\tfor( let i = 0; i < config.playlists[key].songs.length; i++ ){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tCheck to see if the index for the song in the playlist\n\t\t\t\t\t\t\texists in the songs config.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif( !config.songs[ config.playlists[key].songs[i] ] ){\n\t\t\t\t\t\t\tAmplitudeHelpers.writeDebugMessage('The song index: '+config.playlists[key].songs[i]+' in playlist with key: '+key+' is not defined in your songs array!');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Initializes the shuffle statuses for each of the playlists. These will\n\t * be referenced when we shuffle individual playlists.\n\t *\n\t * @access private\n\t */\n\tfunction initializePlaylistShuffleStatuses(){\n\t\t/*\n\t\t\tIterate over all of the playlists the user defined adding\n\t\t\tthe playlist key to the shuffled playlist array and creating\n\t\t\tand empty object to house the statuses.\n\t\t*/\n\t\tfor ( let key in config.playlists ) {\n\t\t\tconfig.shuffled_statuses[ key ] = false;\n\t\t}\n\t}\n\n\t/**\n\t * Initializes the repeat statuses for each of the playlists. These will\n\t * be referenced when we repeat individual playlits.\n\t *\n\t * @access private\n\t */\n\t function initializePlaylistsRepeatStatuses(){\n\t\t /*\n \t\t\tIterate over all of the playlists the user defined adding\n \t\t\tthe playlist key to the repeated playlist array and creating\n \t\t\tand empty object to house the statuses.\n \t\t*/\n \t\tfor ( let key in config.playlists ) {\n \t\t\tconfig.repeat_statuses[ key ] = false;\n \t\t}\n\t }\n\n\t/**\n\t * Initializes the shuffled playlist placeholders. These will be set for\n\t * playlists that are shuffled and contain the shuffled songs.\n\t *\n\t * @access private\n \t */\n\tfunction initializePlaylistShuffleLists(){\n\t\t/*\n\t\t\tIterate over all of the playlists the user defined adding\n\t\t\tthe playlist key to the shuffled playlists array and creating\n\t\t\tand empty object to house the shuffled playlists\n\t\t*/\n\t\tfor ( let key in config.playlists ) {\n\t\t\tconfig.shuffled_playlists[ key ] = [];\n\t\t}\n\t}\n\n\t/**\n\t * Initializes the shuffled playlist indexes array. These will be set for\n\t * playlists that are shuffled and contain the active shuffled index.\n\t *\n\t * @access private\n\t */\n\tfunction initializePlaylistShuffleIndexes(){\n\t\t/*\n\t\t\tIterates over all of the playlists adding a key\n\t\t\tto the shuffled_active_indexes array that contains\n\t\t\tthe active shuffled index.\n\t\t*/\n\t\tfor( let key in config.playlists ) {\n\t\t\tconfig.shuffled_active_indexes[ key ] = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Intializes the display for the first song in the playlist meta data.\n\t *\n\t * @access private\n\t */\n\tfunction initializeFirstSongInPlaylistMetaData(){\n\t\t/*\n\t\t\tIterates over all of the playlists setting the meta data for the\n\t\t\tfirst song.\n\t\t*/\n\t\tfor( let key in config.playlists ){\n\t\t\tAmplitudeVisualSync.setFirstSongInPlaylist( config.songs[ config.playlists[ key ][0] ] , key );\n\t\t}\n\t}\n\n\t/**\n\t * Intializes the default live settings for all of the songs.\n\t *\n\t * @access priavet\n\t */\n\tfunction initializeDefaultLiveSettings(){\n\t\tfor( let i = 0; i < config.songs.length; i++ ){\n\t\t\tif( config.songs[i].live == undefined ){\n\t\t\t\tconfig.songs[i].live = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t\tReturns the publicly accessible methods\n\t*/\n\treturn {\n\t\tinitialize: initialize,\n\t\tsetConfig: setConfig,\n\t\trebindDisplay: rebindDisplay\n\t}\n})();\n\nexport default AmplitudeInitializer\n\n\n\n// WEBPACK FOOTER //\n// ./src/init/init.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the helpers for the event handlers.\n * @module events/AmplitudeEventsHelpers\n */\nimport AmplitudeEventsHelpers from './helpers.js';\n\n/**\n * Imports the visual sync module to keep the display in sync with AmplitudeJS\n * @module visual/AmplitudeVisualSync\n */\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * Imports the core module of Amplitude which handles the basic functions\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * Imports the core helpers for Amplitude which help run some of AmplitudeJS functions\n * @module core/AmplitudeHelpers\n */\nimport AmplitudeCoreHelpers from '../core/helpers.js';\n\n/**\n * These functions handle the events that we bound to each element and\n * prepare for a function to be called. These kind of act like filters/middleware.\n *\n * @module events/AmplitudeHandlers\n */\nexport default {\n\t/**\n\t * When the time updates on the active song, we sync the current time displays\n\t *\n\t * HANDLER FOR: timeupdate\n\t *\n\t * @access public\n\t */\n\tupdateTime: function(){\n\t\t/*\n\t\t\tHelp from: http://jsbin.com/badimipi/1/edit?html,js,output\n\t\t*/\n\t\tif( config.active_song.buffered.length - 1 >= 0 ){\n\t\t\tlet bufferedEnd = config.active_song.buffered.end( config.active_song.buffered.length - 1 );\n\t\t\tlet duration = config.active_song.duration;\n\n\t\t\tconfig.buffered = ( ( bufferedEnd / duration ) * 100 );\n\t\t}\n\n\t\t/*\n\t\t\tSync the buffered progress bars.\n\t\t*/\n\t\tAmplitudeVisualSync.syncBufferedProgressBars();\n\n\t\t/*\n\t\t\tIf the current song is not live, then\n\t\t\twe can update the time information. Otherwise the\n\t\t\tcurrent time updates wouldn't mean much since the time\n\t\t\tis infinite.\n\t\t*/\n\t\tif( !config.active_metadata.live ){\n\t\t\t/*\n\t\t\t\tCompute the current time\n\t\t\t*/\n\t\t\tlet currentTime = AmplitudeEventsHelpers.computeCurrentTimes();\n\n\t\t\t/*\n\t\t\t\tCompute the song completion percentage\n\t\t\t*/\n\t\t\tlet songCompletionPercentage = AmplitudeEventsHelpers.computeSongCompletionPercentage();\n\n\t\t\t/*\n\t\t\t\tComputes the song duration\n\t\t\t*/\n\t\t\tlet songDuration = AmplitudeEventsHelpers.computeSongDuration();\n\n\t\t\t/*\n\t\t\t\tSync the current time elements with the current\n\t\t\t\tlocation of the song and the song duration elements with\n\t\t\t\tthe duration of the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncCurrentTime( currentTime, songCompletionPercentage );\n\t\t\tAmplitudeVisualSync.syncSongDuration( currentTime, songDuration );\n\n\t\t\t/*\n\t\t\t\tRuns the callback defined for the time update.\n\t\t\t*/\n\t\t\tAmplitudeCoreHelpers.runCallback( 'time_update' );\n\t\t}\n\t},\n\n\t/**\n\t * When the keydown event is fired, we determine which function should be run\n\t * based on what was passed in.\n\t *\n\t * HANDLER FOR: keydown\n\t *\n\t * @access public\n\t */\n\tkeydown: function( event ){\n\t\tAmplitudeEventsHelpers.runKeyEvent( event.which );\n\t},\n\n\t/**\n\t * When the song has ended, handles what to do next\n\t *\n\t * HANDLER FOR: ended\n\t *\n\t * @access public\n\t */\n\tsongEnded: function(){\n\t\tif( config.continue_next ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is not set, we set the\n\t\t\t\tnext song that's in the songs array.\n\t\t\t*/\n\t\t\tif( config.active_playlist == ''\n\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\tAmplitudeEventsHelpers.setNext( true );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the next song in the playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( config.active_playlist, true );\n\t\t\t}\n\t\t}else{\n\t\t\tif( !config.is_touch_moving ){\n\t\t\t\t/*\n\t\t\t\t\tSets all of the play/pause buttons to pause\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t\t\t/*\n\t\t\t\t\tStops the active song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCore.stop();\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * As the song is buffered, we can display the buffered percentage in\n\t * a progress bar.\n\t *\n\t * HANDLER FOR: ended\n\t *\n\t * @access public\n\t */\n\tprogress: function(){\n\t\t/*\n\t\t\tHelp from: http://jsbin.com/badimipi/1/edit?html,js,output\n\t\t*/\n\t\tif( config.active_song.buffered.length - 1 >= 0 ){\n\t\t\tlet bufferedEnd = config.active_song.buffered.end( config.active_song.buffered.length - 1 );\n\t\t\tlet duration = config.active_song.duration;\n\n\t\t\tconfig.buffered = ( ( bufferedEnd / duration ) * 100 );\n\t\t}\n\n\t\t/*\n\t\t\tSync the buffered progress bars.\n\t\t*/\n\t\tAmplitudeVisualSync.syncBufferedProgressBars();\n\t},\n\n\t/**\n\t * Handles an event on a play button in Amplitude.\n\t *\n\t * HANDLER FOR: 'amplitude-play'\n\t *\n\t * @access public\n\t * @TODO Finish commenting and re-structure\n\t */\n\tplay: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tGets the attribute for song index so we can check if\n\t\t\t\tthere is a need to change the song. In some scenarios\n\t\t\t\tthere might be multiple play classes on the page. In that\n\t\t\t\tcase it is possible the user could click a different play\n\t\t\t\tclass and change the song.\n\t\t\t*/\n\t\t\tlet playButtonSongIndex = this.getAttribute('amplitude-song-index');\n\t\t\tlet playButtonPlaylistIndex = this.getAttribute('amplitude-playlist');\n\n\t\t\tif( playButtonPlaylistIndex == null && playButtonSongIndex == null ){\n\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( config.active_playlist, config.active_index );\n\t\t\t}\n\n\t\t\t/*\n\n\t\t\t*/\n\t\t\tif( playButtonPlaylistIndex != null && playButtonPlaylistIndex != '' ){\n\t\t\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playButtonPlaylistIndex ) ){\n\t\t\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playButtonPlaylistIndex );\n\n\t\t\t\t\tif( playButtonSongIndex != null ){\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( playButtonSongIndex );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( config.playlists[ playButtonPlaylistIndex ][0] );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tif( playButtonSongIndex != null ){\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( playButtonSongIndex );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( config.active_index );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\n\t\t\t*/\n\t\t\tif( ( playButtonPlaylistIndex == null || playButtonPlaylistIndex == '' )\n\t\t\t\t&& ( playButtonSongIndex != null && playButtonSongIndex != '' ) ){\n\n\t\t\t\t\tif( AmplitudeCoreHelpers.checkNewSong( playButtonSongIndex )\n\t\t\t\t\t\t|| config.active_playlist != playButtonPlaylistIndex ){\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( playButtonSongIndex );\n\t\t\t\t\t}\n\n\t\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( playButtonPlaylistIndex, playButtonSongIndex );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tStart the visualizations for the song.\n\t\t\t\tAMPFX-TODO: MAKE HANDLED BY AMPLITUDE FX\n\t\t\t*/\n\t\t\t//privateStartVisualization();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a pause button\n\t *\n\t * HANDLER FOR: 'amplitude-pause'\n\t *\n\t * @access public\n\t * @TODO Finish commenting and optimize\n\t */\n\tpause: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\tlet pauseButtonSongIndex = this.getAttribute('amplitude-song-index');\n\t\t\tlet pauseButtonPlaylistIndex = this.getAttribute('amplitude-playlist');\n\n\t\t\tif( pauseButtonSongIndex == null && pauseButtonPlaylistIndex == null ){\n\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( config.active_playlist, config.active_index );\n\t\t\t\tAmplitudeCore.pause();\n\t\t\t}\n\n\n\t\t\tif( pauseButtonPlaylistIndex != null || pauseButtonPlaylistIndex != ''\n\t\t\t\t&& config.active_playlist == pauseButtonPlaylistIndex ){\n\t\t\t\t/*\n\t\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\t\tto be paused and we pause the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t\t/*\n\t\t\t\t\tIf there is an active playlist, then\n\t\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\t\tbutton to the state of paused.\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t\t/*\n\t\t\t\t\tSync the song play pause buttons\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t\tAmplitudeCore.pause();\n\t\t\t}\n\n\t\t\tif( ( pauseButtonPlaylistIndex == null || pauseButtonPlaylistIndex == '' )\n\t\t\t\t&& ( pauseButtonSongIndex == config.active_index ) ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\t\t\tto be paused and we pause the song.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf there is an active playlist, then\n\t\t\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\t\t\tbutton to the state of paused.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tSync the song play pause buttons\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t\t\tAmplitudeCore.pause();\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a play/pause button\n\t *\n\t * HANDLER FOR: 'amplitude-play-pause'\n\t *\n\t * @access public\n\t */\n\tplayPause: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tChecks to see if the element has an attribute for amplitude-main-play-pause\n\t\t\t\tand syncs accordingly\n\t\t\t*/\n\t\t\tif( this.getAttribute( 'amplitude-main-play-pause' ) != null ){\n\t\t\t\tAmplitudeEventsHelpers.setMainPlayPause();\n\n\t\t\t/*\n\t\t\t\tSyncs playlist main play pause buttons\n\t\t\t*/\n\t\t\t}else if( this.getAttribute('amplitude-playlist-main-play-pause') != null ){\n\t\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\n\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playlist );\n\n\t\t\t/*\n\t\t\t\tSyncs amplitude individual song buttons\n\t\t\t*/\n\t\t\t}else{\n\t\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\t\t\t\tlet songIndex \t= this.getAttribute('amplitude-song-index');\n\n\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( playlist, songIndex );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a stop element.\n\t *\n\t * HANDLER FOR: 'amplitude-stop'\n\t *\n\t * @access public\n\t * @TODO: AMP-FX Before stopping, make sure that AmplitudeFX visualization is stopped as well.\n\t */\n\tstop: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tSets all of the play/pause buttons to pause\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t\t/*\n\t\t\t\tStops the active song.\n\t\t\t*/\n\t\t\tAmplitudeCore.stop();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event for a mute element\n\t *\n\t * HANDLER FOR: 'amplitude-mute'\n\t *\n\t * @access public\n\t */\n\tmute: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tIf the current volume in the config is 0, we set the volume to the\n\t\t\t\tpre_mute level. This means that the audio is already muted and\n\t\t\t\tneeds to be restored to the pre_mute level.\n\n\t\t\t\tOtherwise, we set pre_mute volume to the current volume\n\t\t\t\tand set the config volume to 0, muting the audio.\n\t\t\t*/\n\t\t\tif( config.volume == 0 ){\n\t\t\t\tconfig.active_song.muted = false;\n\t\t\t\tconfig.volume = config.pre_mute_volume;\n\t\t\t\tAmplitudeVisualSync.syncMute( false );\n\t\t\t}else{\n\t\t\t\tconfig.active_song.muted = true;\n\t\t\t\tconfig.pre_mute_volume = config.volume;\n\t\t\t\tconfig.volume = 0;\n\t\t\t\tAmplitudeVisualSync.syncMute( true );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tCalls the core function to set the volume to the computed value\n\t\t\t\tbased on the user's intent.\n\t\t\t*/\n\t\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t\t/*\n\t\t\t\tSyncs the volume sliders so the visuals align up with the functionality.\n\t\t\t\tIf the volume is at 0, then the sliders should represent that so the user\n\t\t\t\thas the right starting point.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncVolumeSliders( config.volume );\n\t\t}\n\t},\n\n\t/**\n\t * Handles a click on a volume up element.\n\t *\n\t * HANDLER FOR: 'amplitude-volume-up'\n\t *\n\t * @access public\n\t */\n\tvolumeUp: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tThe volume range is from 0 to 1 for an audio element. We make this\n\t\t\t\ta base of 100 for ease of working with.\n\n\t\t\t\tIf the new value is less than 100, we use the new calculated\n\t\t\t\tvalue which gets converted to the proper unit for the audio element.\n\n\t\t\t\tIf the new value is greater than 100, we set the volume to 1 which\n\t\t\t\tis the max for the audio element.\n\t\t\t*/\n\t\t\tif( ( config.volume + config.volume_increment ) <= 100 ){\n\t\t\t\tconfig.volume = config.volume + config.volume_increment;\n\t\t\t}else{\n\t\t\t\tconfig.volume = 100;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tCalls the core function to set the volume to the computed value\n\t\t\t\tbased on the user's intent.\n\t\t\t*/\n\t\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t\t/*\n\t\t\t\tSyncs the volume sliders so the visuals align up with the functionality.\n\t\t\t\tIf the volume is at 0, then the sliders should represent that so the user\n\t\t\t\thas the right starting point.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncVolumeSliders( config.volume );\n\t\t}\n\t},\n\n\t/**\n\t * Handles a click on a volume down element.\n\t *\n\t * HANDLER FOR: 'amplitude-volume-down'\n\t *\n\t * @access public\n\t */\n\tvolumeDown: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tThe volume range is from 0 to 1 for an audio element. We make this\n\t\t\t\ta base of 100 for ease of working with.\n\n\t\t\t\tIf the new value is less than 100, we use the new calculated\n\t\t\t\tvalue which gets converted to the proper unit for the audio element.\n\n\t\t\t\tIf the new value is greater than 100, we set the volume to 1 which\n\t\t\t\tis the max for the audio element.\n\t\t\t*/\n\t\t\tif( ( config.volume - config.volume_increment ) > 0 ){\n\t\t\t\tconfig.volume = config.volume - config.volume_increment;\n\t\t\t}else{\n\t\t\t\tconfig.volume = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tCalls the core function to set the volume to the computed value\n\t\t\t\tbased on the user's intent.\n\t\t\t*/\n\t\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t\t/*\n\t\t\t\tSyncs the volume sliders so the visuals align up with the functionality.\n\t\t\t\tIf the volume is at 0, then the sliders should represent that so the user\n\t\t\t\thas the right starting point.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncVolumeSliders( config.volume );\n\t\t}\n\t},\n\n\t/**\n\t * Handles a change on the song slider\n\t *\n\t * HANDLER FOR: 'amplitude-song-slider'\n\t *\n\t * @access public\n\t */\n\tsongSlider: function(){\n\t\t/*\n\t\t\tGets the percentage of the song we will be setting the location for.\n\t\t*/\n\t\tlet locationPercentage = this.value;\n\n\t\t/*\n\t\t\tChecks to see if the element has an attribute for amplitude-main-play-pause\n\t\t\tand syncs accordingly\n\t\t*/\n\t\tif( this.getAttribute( 'amplitude-main-song-slider' ) != null ){\n\t\t\t/*\n\t\t\t\tIf the active song is not live, set the current time\n\t\t\t*/\n\t\t\tif( !config.active_metadata.live ){\n\t\t\t\tlet currentTime = ( config.active_song.duration ) * ( locationPercentage / 100 );\n\n\t\t\t\tif( isFinite( currentTime ) ){\n\t\t\t\t\tconfig.active_song.currentTime = currentTime;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAmplitudeVisualSync.syncMainSliderLocation( locationPercentage );\n\n\t\t\tif( config.active_playlist != '' && config.active_playlist != null ){\n\t\t\t\tAmplitudeVisualSync.syncPlaylistSliderLocation( config.active_playlist, locationPercentage );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tSyncs playlist main play pause buttons\n\t\t*/\n\t\tif( this.getAttribute('amplitude-playlist-song-slider') != null ){\n\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\n\t\t\t/*\n\t\t\t\tWe don't want to song slide a playlist that's not the\n\t\t\t\tactive placylist.\n\t\t\t*/\n\t\t\tif( config.active_playlist == playlist ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active song is not live, set the current time\n\t\t\t\t*/\n\t\t\t\tif( !config.active_metadata.live ){\n\t\t\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( locationPercentage / 100 );\n\t\t\t\t}\n\t\t\t\tAmplitudeVisualSync.syncMainSliderLocation( locationPercentage );\n\t\t\t\tAmplitudeVisualSync.syncPlaylistSliderLocation( playlist, locationPercentage );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tSyncs amplitude individual song buttons\n\t\t*/\n\t\tif( this.getAttribute('amplitude-playlist-song-slider') == null\n\t\t\t&& this.getAttribute('amplitude-main-song-slider') == null ){\n\n\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\t\t\tlet songIndex \t= this.getAttribute('amplitude-song-index');\n\n\t\t\tif( config.active_index == songIndex ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active song is not live, set the current time\n\t\t\t\t*/\n\t\t\t\tif( !config.active_metadata.live ){\n\t\t\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( locationPercentage / 100 );\n\t\t\t\t}\n\n\t\t\t\tAmplitudeVisualSync.syncMainSliderLocation();\n\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& config.active_playlist == playlist ){\n\t\t\t\t\t\tAmplitudeVisualSync.syncPlaylistSliderLocation( playlist, location );\n\t\t\t\t}\n\n\t\t\t\tAmplitudeVisualSync.syncSongSliderLocation( playlist, songIndex, location );\n\t\t\t}\n\t\t}\n\n\t},\n\n\t/**\n\t * Handles a change on the volume slider\n\t *\n\t * HANDLER FOR: 'amplitude-volume-slider'\n\t *\n\t * @access public\n\t */\n\tvolumeSlider: function(){\n\t\t/*\n\t\t\tCalls the core function to set the volume to the computed value\n\t\t\tbased on the user's intent.\n\t\t*/\n\t\tAmplitudeCore.setVolume( this.value );\n\n\t\t/*\n\t\t\tSync the volume slider locations\n\t\t*/\n\t\tAmplitudeVisualSync.syncVolumeSliderLocation( this.value );\n\t},\n\n\t/**\n\t * Handles an event on the next button\n\t *\n\t * HANDLER FOR: 'amplitude-next'\n\t *\n\t * @access public\n\t */\n\tnext: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tChecks to see if the button is a playlist next button or\n\t\t\t\tif it's a global playlist button.\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\n\t\t\t\t/*\n\t\t\t\t\tCheck to see if the current state of the player\n\t\t\t\t\tis in playlist mode or not playlist mode.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\tAmplitudeEventsHelpers.setNext();\n\t\t\t\t}else{\n\t\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( config.active_playlist );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the playlist of the next button.\n\t\t\t\t*/\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\n\t\t\t\t/*\n\t\t\t\t\tSets the next playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( playlist );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the previous button\n\t *\n\t * HANDLER FOR: 'amplitude-prev'\n\t *\n\t * @access public\n\t */\n\tprev: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tChecks to see if the previous button is a playlist previous\n\t\t\t\tbutton or if it's a global playlist button.\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\n\t\t\t\t/*\n\t\t\t\t\tCheck to see if the current playlist has been set\n\t\t\t\t\tor null and set the previous song.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPrev();\n\t\t\t\t}else{\n\t\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( config.active_playlist );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the playlist of the previous button.\n\t\t\t\t*/\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\n\t\t\t\t/*\n\t\t\t\t\tSets the previous playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( playlist );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the shuffle button\n\t *\n\t * HANDLER FOR: 'amplitude-shuffle'\n\t *\n\t * @access public\n\t */\n\tshuffle: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tCheck to see if the shuffle button belongs to a playlist\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\t\t\t\t/*\n\t\t\t\t\tSets the shuffle button to null\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setShuffle( null );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the playlist attribute of the shuffle button and\n\t\t\t\t\tset shuffle to on for the playlist.\n\t\t\t\t*/\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\t\t\t\tAmplitudeEventsHelpers.setShuffle( playlist );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the repeat button\n\t *\n\t * HANDLER FOR: 'amplitude-repeat'\n\t *\n\t * @access private\n\t */\n\trepeat: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tCheck to see if the repeat button belongs to a playlist\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets repeat to the opposite of what it was set to\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat, null );\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tGets the playlist attribute of the repeat button and\n\t\t\t\t\t\tset repeat to on for the playlist.\n\t\t\t\t\t*/\n\t\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\t\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat_statuses[playlist], playlist );\n\t\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the repeat song button\n\t *\n\t * HANDLER FOR: 'amplitude-repeat-song'\n\t *\n\t * @access private\n\t */\n\trepeatSong: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tSets repeat song to the opposite of what it was set to\n\t\t\t*/\n\t\t\tAmplitudeEventsHelpers.setRepeatSong( !config.repeat_song );\n\n\t\t\t/*\n\t\t\t\tVisually sync repeat song\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncRepeatSong();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the playback speed button\n\t *\n\t * HANDLER FOR: 'amplitude-playback-speed'\n\t *\n\t * @access private\n\t */\n\tplaybackSpeed: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tWe increment the speed by .5 everytime we click\n\t\t\t\tthe button to change the playback speed. Once we are\n\t\t\t\tactively playing back at 2, we start back at 1 which\n\t\t\t\tis normal speed.\n\t\t\t*/\n\t\t\tswitch( config.playback_speed ){\n\t\t\t\tcase 1:\n\t\t\t\t\tAmplitudeEventsHelpers.setPlaybackSpeed( 1.5 );\n\t\t\t\tbreak;\n\t\t\t\tcase 1.5:\n\t\t\t\t\tAmplitudeEventsHelpers.setPlaybackSpeed( 2 );\n\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tAmplitudeEventsHelpers.setPlaybackSpeed( 1 );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tVisually sync the playback speed.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaybackSpeed();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a skip to button.\n\t *\n\t * HANDLER FOR: 'amplitude-skip-to'\n\t *\n\t * @access private\n\t */\n\tskipTo: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tDetermines if the skip to button is in the scope of a playlist.\n\t\t\t*/\n\t\t\tif( this.hasAttribute('amplitude-playlist') ){\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\n\t\t\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\t\t\t\t}\n\t\t\t\t/*\n\t\t\t\t\tGets the location, playlist and song index that is being skipped\n\t\t\t\t\tto.\n\t\t\t\t*/\n\t\t\t\tlet seconds = parseInt( this.getAttribute('amplitude-location') );\n\t\t\t\tlet songIndex = parseInt( this.getAttribute( 'amplitude-song-index') );\n\n\t\t\t\t/*\n\t\t\t\t\tChanges the song to where it's being skipped and then\n\t\t\t\t\tplay the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t\t\tAmplitudeCore.play();\n\n\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( playlist, 'playing' );\n\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, songIndex, 'playing' );\n\n\t\t\t\t/*\n\t\t\t\t\tSkip to the location in the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCore.skipToLocation( seconds );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the location and song index that is being skipped\n\t\t\t\t\tto.\n\t\t\t\t*/\n\t\t\t \tlet seconds = parseInt( this.getAttribute('amplitude-location') );\n\t\t\t \tlet songIndex = parseInt( this.getAttribute( 'amplitude-song-index') );\n\n\t\t\t\t/*\n\t\t\t\t\tChanges the song to where it's being skipped and then\n\t\t\t\t\tplay the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t\t\tAmplitudeCore.play();\n\n\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( null, songIndex, 'playing' );\n\n\t\t\t\t/*\n\t\t\t\t\tSkip to the location in the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCore.skipToLocation( seconds );\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/events/handlers.js","/**\n * @name \t\tAmplitude.js\n * @version 3.3.0\n * @author \tDan Pastori (521 Dimensions) \n*/\n\n/**\n * AmplitudeJS Initializer Module\n *\n * @module init/AmplitudeInitializer\n */\nimport AmplitudeInitializer from './init/init.js';\n\n/**\n * AmplitudeJS Core Module\n *\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from './core/core.js';\n\n/**\n * AmplitudeJS Core Helpers Module\n *\n * @module core/AmplitudeCoreHelpers\n */\nimport AmplitudeCoreHelpers from './core/helpers.js';\n\n/**\n * AmplitudeJS Events Module\n *\n * @module events/AmplitudeEvents\n */\nimport AmplitudeEvents from './events/events.js';\n\n/**\n * AmplitudeJS Events Helpers Module\n *\n * @module events/AmplitudeEventsHelpers\n */\nimport AmplitudeEventsHelpers from './events/helpers.js';\n\n/**\n * AmplitudeJS Visual Sync Module\n *\n * @module visual/AmplitudeVisualSync\n */\nimport AmplitudeVisualSync from './visual/visual.js';\n\n/**\n * Imports the config module\n * @module config\n */\nimport config from './config.js';\n\n/**\n * Amplitude should just be an interface to the public functions.\n * Everything else should be handled by other objects\n *\n * @module Amplitude\n */\n\nlet Amplitude = (function () {\n\t/**\n\t * The main init function. The user will call this through\n\t * Amplitude.init({}) and pass in their settings.\n\t *\n\t * Public Accessor: Amplitude.init( user_config_json );\n\t *\n\t * @access public\n\t * @param {object} userConfig \t- A JSON object of user defined values that helps configure and initialize AmplitudeJS.\n\t */\n\tfunction init( userConfig ){\n\t\tAmplitudeInitializer.initialize( userConfig );\n\t}\n\n\t/**\n\t * Binds new elements that were added to the page.\n\t *\n\t * Public Accessor: Amplitude.bindNewElements()\n\t *\n\t * @access public\n\t */\n\tfunction bindNewElements(){\n\t\tAmplitudeInitializer.rebindDisplay();\n\t}\n\n\t/**\n\t * Returns the active playlist.\n\t *\n\t * Public Accessor: Amplitude.getActivePlaylist()\n\t *\n\t * @access public\n\t */\n\tfunction getActivePlaylist(){\n\t\treturn config.active_playlist;\n\t}\n\n\t/**\n\t * Returns the current playback speed.\n\t *\n\t * Public Accessor: Amplitude.getPlaybackSpeed()\n\t *\n\t * @access public\n\t */\n\tfunction getPlaybackSpeed(){\n\t\treturn config.playback_speed;\n\t}\n\n\t/**\n\t * Gets the repeat state of the player.\n\t *\n\t * Public Accessor: Amplitude.getRepeat()\n\t *\n\t * @access public\n\t */\n\tfunction getRepeat(){\n\t\treturn config.repeat;\n\t}\n\n\t/**\n\t * Returns the shuffle state of the player.\n\t *\n\t * Public Accessor: Amplitude.getShuffle()\n\t *\n\t * @access public\n\t */\n\tfunction getShuffle(){\n\t\treturn config.shuffle_on\n\t}\n\n\t/**\n\t * Returns the shuffle state of the playlist.\n\t *\n\t * Public Accessor: Amplitude.getShufflePlaylist( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The key representing the playlist ID to see if it's shuffled or not.\n\t */\n\tfunction getShufflePlaylist( playlist ){\n\t\treturn config.shuffled_statuses[ playlist ];\n\t}\n\n\t/**\n\t * Sets the shuffle state for the player.\n\t *\n\t * Public Accessor: Amplitude.setShuffle()\n\t *\n\t * @access public\n\t */\n\t function setShuffle(){\n\t\t AmplitudeEventsHelpers.setShuffle( null );\n\t }\n\n\t /**\n \t * Sets the shuffle state for the playlist\n \t *\n \t * Public Accessor: Amplitude.setShufflePlaylist( playlistKey )\n \t *\n \t * @access public\n\t * @param {string} playlistKey \t- The key representing the playlist ID to to shuffle the playlist.\n \t */\n \t function setShufflePlaylist( playlistKey ){\n \t\t AmplitudeEventsHelpers.setShuffle( playlistKey );\n \t }\n\n\t /**\n\t * Sets the repeat state for the player.\n\t\t*\n\t\t* Public Accessor: Amplitude.setRepeat()\n\t\t*\n\t\t* @access public\n\t */\n\t\tfunction setRepeat(){\n\t\t\tif( !config.is_touch_moving ){\n\t\t\t\t/*\n\t\t\t\t\tSets repeat to the opposite of what it was set to\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat );\n\n\t\t\t\t/*\n\t\t\t\t\tVisually sync repeat\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncRepeat();\n\t\t\t}\n\t\t}\n\n\t/**\n\t * Sets the repeat state for the song.\n\t *\n\t * Public Accessor: Amplitude.setRepeatSong()\n\t *\n\t * @access public\n\t */\n\t function setRepeatSong(){\n\t\t if( !config.is_touch_moving ){\n\t\t\t /*\n\t\t\t\t Sets repeat to the opposite of what it was set to\n\t\t\t */\n\t\t\t AmplitudeEventsHelpers.setRepeatSong( !config.repeat_song );\n\n\t\t\t /*\n\t\t\t\t Visually sync repeat song\n\t\t\t */\n\t\t\t AmplitudeVisualSync.syncRepeatSong();\n\t\t }\n\t }\n\n\n\t/**\n\t * Gets the default album art for the player\n\t *\n\t * Public Accessor: Amplitude.getDefaultAlbumArt()\n\t *\n\t * @access public\n\t */\n\tfunction getDefaultAlbumArt(){\n\t\treturn config.default_album_art;\n\t}\n\n\t/**\n\t * Sets the default album art for the player\n\t *\n\t * Public Accessor: Amplitude.setDefaultAlbumArt( url )\n\t *\n\t * @access public\n\t * @param {string} url \t- A string representing the URL of the new default album art.\n\t */\n\tfunction setDefaultAlbumArt( url ){\n\t\tconfig.default_album_art = url;\n\t}\n\n\t/**\n\t * Allows the user to get the percentage of the song played.\n\t *\n\t * Public Accessor: Amplitude.getSongPlayedPercentage();\n\t *\n\t * @access public\n\t */\n\tfunction getSongPlayedPercentage(){\n\t\t/*\n\t\t\tReturns the percentage of the song played.\n\t\t*/\n\t\treturn ( config.active_song.currentTime / config.active_song.duration ) * 100;\n\t}\n\n\t/**\n\t * Allows the user to set how far into the song they want to be. This is\n\t * helpful for implementing custom range sliders. Only works on the current song.\n\t *\n\t * Public Accessor: Amplitude.setSongPlayedPercentage( float );\n\t *\n\t * @access public\n\t * @param {number} percentage \t- The percentage of the song played\n\t */\n\tfunction setSongPlayedPercentage( percentage ){\n\t\t/*\n\t\t\tEnsures the percentage is a number and is between 0 and 100.\n\t\t*/\n\t\tif( typeof percentage == 'number'\n\t\t\t&& ( percentage > 0 && percentage < 100 ) ){\n\t\t\t\t/*\n\t\t\t\t\tSets the current time of the song to the percentage.\n\t\t\t\t*/\n\t\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( percentage / 100 );\n\t\t}\n\t}\n\n\t/**\n\t * Allows the user to turn on debugging.\n\t *\n\t * Public Accessor: Amplitude.setDebug( bool );\n\t *\n\t * @access public\n\t * @param {boolean} state \t\t- Turns debugging on and off.\n\t */\n\tfunction setDebug( state ){\n\t\t/*\n\t\t\tSets the global config debug on or off.\n\t\t*/\n\t\tconfig.debug = state;\n\t}\n\n\t/**\n\t * Returns the active song meta data for the user to do what is\n\t * needed.\n\t *\n\t * Public Accessor: Amplitude.getActiveSongMetadata();\n\t *\n\t * @access public\n\t * @returns {object} JSON Object with the active song information\n\t */\n\tfunction getActiveSongMetadata(){\n\t\treturn config.active_metadata;\n\t}\n\n\t/**\n\t * Returns a song in the songs array at that index\n\t *\n\t * Public Accessor: Amplitude.getSongByIndex( song_index )\n\t *\n\t * @access public\n\t * @param {number} index \t- The integer for the index of the song in the songs array.\n\t * @returns {object} JSON representation for the song at a specific index.\n\t */\n\tfunction getSongByIndex( index ){\n\t\treturn config.songs[index];\n\t}\n\n\t/**\n\t * Returns a song at a playlist index\n\t *\n\t * Public Accessor: Amplitude.getSongAtPlaylistIndex( playlist, index\n\t *\n\t * @access public\n\t * @param {number} index \t\t\t- The integer for the index of the song in the playlist.\n\t * @param {string} playlist\t\t- The key of the playlist we are getting the song at the index for\n\t * @returns {object} JSON representation for the song at a specific index.\n\t */\n\tfunction getSongAtPlaylistIndex( playlist, index ){\n\t\tlet songIndex = config.playlists[playlist][index];\n\n\t\treturn config.songs[songIndex];\n\t}\n\n\t/**\n\t * Adds a song to the end of the config array. This will allow Amplitude\n\t * to play the song in a playlist type setting.\n\t *\n\t * Public Accessor: Amplitude.addSong( song_json )\n\t *\n\t * @access public\n\t * @param {object} song \t- JSON representation of a song.\n\t * @returns {number} New index of the song.\n\t */\n\tfunction addSong( song ){\n\t\t/*\n\t\t\tEnsures we have a songs array to push to.\n\t\t*/\n\t\tif( config.songs == undefined ){\n\t\t\tconfig.songs = [];\n\t\t}\n\n\t\tconfig.songs.push( song );\n\t\tAmplitudeEventsHelpers.setNext();\n\t\treturn config.songs.length - 1;\n\t}\n\n\t/**\n\t * Adds a song to a playlist. This will allow Amplitude to play the song in the\n\t * playlist\n\t *\n\t * Public Accessor: Amplitude.addSongToPlaylist( song_json, playlist_key )\n\t *\n\t * @access public\n\t * @param {object} song \t\t\t- JSON representation of a song.\n\t * @param {string} playlist\t\t- Playlist we are adding the song to.\n\t * @returns {mixed} New index of song in playlist or null if no playlist exists\n\t */\n\t function addSongToPlaylist( song, playlist ){\n\t\t \t/*\n\t \t\t\tEnsures we have a songs array to push to. This is step 1.\n\t \t\t*/\n\t \t\tif( config.songs == undefined ){\n\t \t\t\tconfig.songs = [];\n\t \t\t}\n\n\t \t\tconfig.songs.push( song );\n\n\t\t\tvar songIndex = config.songs.length - 1;\n\n\t\t\t/*\n\t\t\t\tEnsures the playlist is valid to push the song on to.\n\t\t\t*/\n\t\t\tif( config.playlists[playlist] != undefined ){\n\t\t\t\tconfig.playlists[playlist].push( songIndex );\n\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( playlist );\n\n\t\t\t\treturn config.playlists[playlist].length - 1;\n\t\t\t}else{\n\t\t\t\treturn null;\n\t\t\t}\n\t }\n\n\t /**\n \t * Removes a song from the song array\n \t *\n \t * Public Accessor: Amplitude.removeSong( index )\n \t *\n \t * @access public\n \t * @param {integer} index \t\t\t- Index of the song being removed\n \t * @returns {boolean} True if removed false if not.\n \t */\n\t function removeSong( index ){\n\t\t if( config.songs[index] != undefined ){\n\t\t\t config.songs.splice( index, 1 );\n\t\t\t return true;\n\t\t }else{\n\t\t \treturn false;\n\t\t }\n\t }\n\n\t /**\n \t * Removes a song from the playlist\n \t *\n \t * Public Accessor: Amplitude.removeSongFromPlaylist( index, playlist )\n \t *\n \t * @access public\n \t * @param {integer} index \t\t\t- Index of the song being removed from the playlist.\n \t * @param {string} playlist\t\t\t- Playlist we are removing the song from.\n \t * @returns {boolean} True if removed false if not.\n \t */\n\t function removeSongFromPlaylist( index, playlist ){\n\t\t if( config.playlists[playlist] != undefined ){\n\t\t\t config.playlists[playlist].splice( index, 1 );\n\t\t }else{\n\t\t\t return false;\n\t\t }\n\t }\n\n\t/**\n\t * When you pass a song object it plays that song right awawy. It sets\n\t * the active song in the config to the song you pass in and synchronizes\n\t * the visuals.\n\t *\n\t * Public Accessor: Amplitude.playNow( song )\n\t *\n\t * @access public\n\t * @param {object} song \t- JSON representation of a song.\n\t */\n\tfunction playNow( song ){\n\t\tAmplitudeCore.playNow( song );\n\t}\n\n\t/**\n\t * Plays a song at the index passed in from the songs array.\n\t *\n\t * Public Accessor: Amplitude.playSongAtIndex( index )\n\t *\n\t * @access public\n\t * @param {number} index \t- The number representing the song in the songs array.\n\t */\n\tfunction playSongAtIndex( index ){\n\t\tAmplitudeCore.playSongAtIndex( index );\n\t}\n\n\t/**\n\t * Plays a song at the index passed in for the playlist provided. The index passed\n\t * in should be the index of the song in the playlist and not the songs array.\n\t *\n\t * @access public\n\t * @param {number} index \t\t- The number representing the song in the playlist array.\n\t * @param {string} playlist - The key string representing the playlist we are playing the song from.\n\t *\n\t */\n\tfunction playPlaylistSongAtIndex( index, playlist ){\n\t\tAmplitudeCore.playPlaylistSongAtIndex( index, playlist );\n\t}\n\n\t/**\n\t * @TODO: Implement Add Song To Playlist Functionality\n\t */\n\tfunction addSongToPlaylist( song, playlist ){\n\n\t}\n\n\t/**\n\t * Allows the user to play whatever the active song is directly\n\t * through Javascript. Normally ALL of Amplitude functions that access\n\t * the core features are called through event handlers.\n\t *\n\t * Public Accessor: Amplitude.play();\n\t *\n\t * @access public\n\t */\n\tfunction play(){\n\t\tAmplitudeCore.play();\n\t}\n\n\t/**\n\t * Allows the user to pause whatever the active song is directly\n\t * through Javascript. Normally ALL of Amplitude functions that access\n\t * the core features are called through event handlers.\n\t *\n\t * Public Accessor: Amplitude.pause();\n\t *\n\t * @access public\n\t */\n\tfunction pause(){\n\t\tAmplitudeCore.pause();\n\t}\n\n\t/**\n\t * Returns the audio object used to play the audio\n\t *\n\t * Public Accessor: Amplitude.getAudio();\n\t *\n\t * @access public\n\t */\n\tfunction getAudio(){\n\t\treturn config.active_song;\n\t}\n\n\t/**\n\t * Plays the next song either in the playlist or globally.\n\t *\n\t * Public Accessor: Amplitude.next( playlist );\n\t *\n\t * @access public\n\t * @param {string} [playlist = null] \t- The playlist key\n\t */\n\tfunction next( playlist = null ){\n\t\t/*\n\t\t\tIf the playlist is empty or null, then we check the active\n\t\t\tplaylist\n\t\t*/\n\t\tif( playlist == '' || playlist == null ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is null, then we set the next global\n\t\t\t\tsong or we set the next in the playlist.\n\t\t\t*/\n\t\t\tif( config.active_playlist == null || config.active_playlist == '' ){\n\t\t\t\tAmplitudeEventsHelpers.setNext()\n\t\t\t}else{\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( config.active_playlist );\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tSet the next in the playlist for the key provided.\n\t\t\t*/\n\t\t\tAmplitudeEventsHelpers.setNextPlaylist( playlist );\n\t\t}\n\t}\n\n\t/**\n\t * Plays the prev song either in the playlist or globally.\n\t *\n\t * Public Accessor: Amplitude.prev( playlist );\n\t *\n\t * @access public\n\t * @param {string} [playlist = null] \t- The playlist key\n\t */\n\tfunction prev( playlist = null ){\n\t\t/*\n\t\t\tIf the playlist is empty or null, then we check the active\n\t\t\tplaylist\n\t\t*/\n\t\tif( playlist == '' || playlist == null ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is null, then we set the prev global\n\t\t\t\tsong or we set the prev in the playlist.\n\t\t\t*/\n\t\t\tif( config.active_playlist == null || config.active_playlist == '' ){\n\t\t\t\tAmplitudeEventsHelpers.setPrev()\n\t\t\t}else{\n\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( config.active_playlist );\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tSet the prev in the playlist for the key provided.\n\t\t\t*/\n\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( playlist );\n\t\t}\n\t}\n\n\t/**\n\t * Gets all of the songs in the songs array\n\t *\n\t * Public Accessor: Amplitude.getSongs( );\n\t *\n\t * @access public\n\t */\n\tfunction getSongs(){\n\t\treturn config.songs;\n\t}\n\n\t/**\n\t * Gets all of the songs in a playlist\n\t *\n\t * Public Accessor: Amplitude.getSongsInPlaylist( playlist );\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist key\n\t */\n\tfunction getSongsInPlaylist( playlist ){\n\t\tlet songsArray = [];\n\n\t\tfor( let i = 0; i < config.playlists[playlist].length; i++ ){\n\t\t\tsongsArray.push( config.songs[i] );\n\t\t}\n\n\t\treturn songsArray;\n\t}\n\n\t/**\n\t * Get current state of songs. If shuffled, this will return the shuffled\n\t * songs.\n\t *\n\t * Public Accessor: Amplitude.getSongsState();\n\t *\n\t * @access public\n\t */\n\tfunction getSongsState(){\n\t\tif( config.shuffle_on ){\n\t\t\treturn config.shuffle_list;\n\t\t}else{\n\t\t\treturn config.songs;\n\t\t}\n\t}\n\n\t/**\n\t * Get current state of songs in playlist. If shuffled, this will return the\n\t * shuffled songs.\n\t *\n\t * Public Accessor: Amplitude.getSongsStatePlaylist( playlist );\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist key\n\t * @todo Finish commenting\n\t */\n\tfunction getSongsStatePlaylist( playlist ){\n\t\tlet songsArray = [];\n\n\t\tif( config.shuffled_status[playlist] ){\n\n\t\t\tfor( let i = 0; i < config.shuffled_playlists[playlist].length; i++ ){\n\t\t\t\tsongsArray.push( config.songs[i] );\n\t\t\t}\n\n\t\t}else{\n\n\t\t\tfor( let i = 0; i < config.playlists[playlist].length; i++ ){\n\t\t\t\tsongsArray.push( config.songs[i] );\n\t\t\t}\n\t\t}\n\n\t\treturn songsArray;\n\t}\n\n\t/**\n\t * Gets the active index of the player\n\t *\n\t * Public Accessor: Amplitude.getActiveIndex()\n\t *\n\t * @access public\n\t */\n\tfunction getActiveIndex(){\n\t\treturn parseInt( config.active_index );\n\t}\n\n\t/**\n\t * Gets the active index with respect to the state of the player whether it is\n\t * shuffled or not.\n\t *\n\t * Public Accessor: Amplitude.getActiveIndexState()\n\t *\n\t * @access public\n\t */\n\tfunction getActiveIndexState(){\n\t\tif( config.shuffle_on ){\n\t\t\treturn parseInt( config.shuffle_active_index );\n\t\t}else{\n\t\t\treturn parseInt( config.active_index );\n\t\t}\n\t}\n\n\t/**\n\t * Get the version of AmplitudeJS\n\t *\n\t * Public Accessor: Amplitude.getVersion()\n\t *\n\t * @access public\n\t */\n\tfunction getVersion(){\n\t\treturn config.version;\n\t}\n\n\t/**\n\t * Get the buffered amount for the current song\n\t *\n\t * Public Accessor: Amplitude.getBuffered()\n\t *\n\t * @access public\n\t */\n\tfunction getBuffered(){\n\t\treturn config.buffered;\n\t}\n\n\t/**\n\t * Skip to a certain location in a selected song.\n\t *\n\t * Public Accessor: Amplitude.getBuffered()\n\t *\n\t * @access public\n\t * @param {number} seconds \t\t\t\t\t\t- The amount of seconds we should skip to in the song.\n\t * @param {number} songIndex \t\t\t\t\t- The index of the song in the songs array.\n\t * @param {string} [playlist = null]\t- The playlist the song we are skipping to belogns to.\n\t */\n\tfunction skipTo( seconds, songIndex, playlist = null ){\n\t\tif( playlist != null ){\n\t\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\t\t\t}\n\t\t}\n\n\t\tseconds = parseInt( seconds );\n\n\t\t/*\n\t\t\tChanges the song to where it's being skipped and then\n\t\t\tplay the song.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\tAmplitudeCore.play();\n\n\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\tif( playlist != null ){\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( playlist, 'playing' );\n\t\t}\n\n\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, songIndex, 'playing' );\n\n\t\t/*\n\t\t\tSkip to the location in the song.\n\t\t*/\n\t\tAmplitudeCore.skipToLocation( seconds );\n\t}\n\n\t/*\n\t\tReturns all of the publically accesible methods.\n\t*/\n\treturn {\n\t\tinit: init,\n\t\tbindNewElements: bindNewElements,\n\t\tgetActivePlaylist: getActivePlaylist,\n\t\tgetPlaybackSpeed: getPlaybackSpeed,\n\t\tgetRepeat: getRepeat,\n\t\tgetShuffle: getShuffle,\n\t\tgetShufflePlaylist: getShufflePlaylist,\n\t\tsetShuffle: setShuffle,\n\t\tsetShufflePlaylist: setShufflePlaylist,\n\t\tsetRepeat: setRepeat,\n\t\tsetRepeatSong: setRepeatSong,\n\t\tgetDefaultAlbumArt: getDefaultAlbumArt,\n\t\tsetDefaultAlbumArt: setDefaultAlbumArt,\n\t\tgetSongPlayedPercentage: getSongPlayedPercentage,\n\t\tsetSongPlayedPercentage: setSongPlayedPercentage,\n\t\tsetDebug: setDebug,\n\t\tgetActiveSongMetadata: getActiveSongMetadata,\n\t\tgetSongByIndex: getSongByIndex,\n\t\tgetSongAtPlaylistIndex: getSongAtPlaylistIndex,\n\t\taddSong: addSong,\n\t\taddSongToPlaylist: addSongToPlaylist,\n\t\tremoveSong: removeSong,\n\t\tremoveSongFromPlaylist: removeSongFromPlaylist,\n\t\tplayNow: playNow,\n\t\tplaySongAtIndex: playSongAtIndex,\n\t\tplayPlaylistSongAtIndex: playPlaylistSongAtIndex,\n\t\tplay: play,\n\t\tpause: pause,\n\t\taudio: getAudio,\n\t\tnext: next,\n\t\tprev: prev,\n\t\tgetSongs: getSongs,\n\t\tgetSongsInPlaylist: getSongsInPlaylist,\n\t\tgetSongsState: getSongsState,\n\t\tgetSongsStatePlaylist: getSongsStatePlaylist,\n\t\tgetActiveIndex: getActiveIndex,\n\t\tgetActiveIndexState: getActiveIndexState,\n\t\tgetVersion: getVersion,\n\t\tgetBuffered: getBuffered,\n\t\tskipTo: skipTo\n\t}\n})();\n\nexport default Amplitude;\n\n\n\n// WEBPACK FOOTER //\n// ./src/index.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the helper functions for the core module\n * @module core/AmplitudeHelers\n */\nimport AmplitudeHelpers from '../core/helpers.js';\n\n/**\n * Imports the initializer\n * @module init/AmplitudeInitializer\n */\nimport AmplitudeInitializer from '../init/init.js';\n\n/**\n * These helpers wrap around the basic methods of the Soundcloud API\n * and get the information we need from SoundCloud to make the songs\n * streamable through Amplitude\n *\n * @module soundcloud/AmplitudeSoundcloud\n */\nlet AmplitudeSoundcloud = (function() {\n\n\t/**\n\t * Defines the temporary user config used while we configure soundcloud\n\t * @type {object}\n\t */\n\tlet tempUserConfig = {};\n\n\t/**\n\t * Loads the soundcloud SDK for use with Amplitude so the user doesn't have\n\t * to load it themselves.\n\t * With help from: http://stackoverflow.com/questions/950087/include-a-javascript-file-in-another-javascript-file\n\t *\n\t * @access public\n\t * @param {object} userConfig \t- The config defined by the user for AmplitudeJS\n\t */\n\tfunction loadSoundCloud( userConfig ){\n\t\t/*\n\t\t\tSets the temporary config to the config passed by the user so we can make changes\n\t\t\tand not break the actual config.\n\t\t*/\n\t\ttempUserConfig = userConfig;\n\n\t\t/*\n\t\t\tGets the head tag for the document and create a script element.\n\t\t*/\n\t\tlet head = document.getElementsByTagName('head')[0];\n\t\tlet script = document.createElement('script');\n\n\t\tscript.type = 'text/javascript';\n\n\t\t/*\n\t\t\tURL to the remote soundcloud SDK\n\t\t*/\n\t\tscript.src = 'https://connect.soundcloud.com/sdk.js';\n\t\tscript.onreadystatechange = initSoundcloud;\n\t\tscript.onload = initSoundcloud;\n\n\t\t/*\n\t\t\tAdd the script to the head of the document.\n\t\t*/\n\t\thead.appendChild( script );\n\t}\n\n\t/**\n\t * Initializes soundcloud with the key provided.\n\t *\n\t * @access private\n\t */\n\tfunction initSoundcloud(){\n\t\t/*\n\t\t\tCalls the SoundCloud initialize function\n\t\t\tfrom their API and sends it the client_id\n\t\t\tthat the user passed in.\n\t\t*/\n\t\tSC.initialize({\n\t\t\tclient_id: config.soundcloud_client\n\t\t});\n\n\t\t/*\n\t\t\tGets the streamable URLs to run through Amplitue. This is\n\t\t\tVERY important since Amplitude can't stream the copy and pasted\n\t\t\tlink from the SoundCloud page, but can resolve the streaming\n\t\t\tURLs from the link.\n\t\t*/\n\t\tgetStreamableURLs();\n\t}\n\n\t/**\n\t * Gets the streamable URL from the URL provided for\n\t * all of the soundcloud links. This will loop through\n\t * and set all of the information for the soundcloud\n\t * urls.\n\t *\n\t * @access private\n\t */\n\tfunction getStreamableURLs(){\n\t\t/*\n\t\t\tDefine the regex to find the soundcloud URLs\n\t\t*/\n\t\tlet soundcloud_regex = /^https?:\\/\\/(soundcloud.com|snd.sc)\\/(.*)$/;\n\n\t\tfor( let i = 0; i < config.songs.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the URL matches soundcloud, we grab\n\t\t\t\tthat url and get the streamable link\n\t\t\t\tif there is one.\n\t\t\t*/\n\t\t\tif( config.songs[i].url.match( soundcloud_regex ) ){\n\t\t\t\tconfig.soundcloud_song_count++;\n\t\t\t\tresolveStreamable(config.songs[i].url, i);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Due to Soundcloud SDK being asynchronous, we need to scope the\n\t * index of the song in another function. The privateGetSoundcloudStreamableURLs\n\t * function does the actual iteration and scoping.\n\t *\n\t * @access private\n\t * @param {string} url \t\t- URL of the soundcloud song\n\t * @param {number} index \t- The index of the soundcloud song in the songs array.\n\t */\n\tfunction resolveStreamable( url, index ){\n\t\tSC.get('/resolve/?url='+url, function( sound ){\n\t\t\t/*\n\t\t\t\tIf streamable we get the url and bind the client ID to the end\n\t\t\t\tso Amplitude can just stream the song normally. We then overwrite\n\t\t\t\tthe url the user provided with the streamable URL.\n\t\t\t*/\n\t\t\tif( sound.streamable ){\n\t\t\t\tconfig.songs[index].url = sound.stream_url+'?client_id='+config.soundcloud_client;\n\n\t\t\t\t/*\n\t\t\t\t\tIf the user want's to use soundcloud art, we overwrite the\n\t\t\t\t\tcover_art_url with the soundcloud artwork url.\n\t\t\t\t*/\n\t\t\t\tif( config.soundcloud_use_art ){\n\t\t\t\t\tconfig.songs[index].cover_art_url = sound.artwork_url;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t\tGrab the extra metadata from soundcloud and bind it to the\n\t\t\t\t\tsong. The user can get this through the public function:\n\t\t\t\t\tgetActiveSongMetadata\n\t\t\t\t*/\n\t\t\t\tconfig.songs[index].soundcloud_data = sound;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf not streamable, then we print a message to the user stating\n\t\t\t\t\tthat the song with name X and artist X is not streamable. This\n\t\t\t\t\tgets printed ONLY if they have debug turned on.\n\t\t\t\t*/\n\t\t\t\tAmplitudeHelpers.writeDebugMessage( config.songs[index].name +' by '+config.songs[index].artist +' is not streamable by the Soundcloud API' );\n\t\t\t}\n\t\t\t/*\n\t\t\t\tIncrements the song ready counter.\n\t\t\t*/\n\t\t\tconfig.soundcloud_songs_ready++;\n\n\t\t\t/*\n\t\t\t\tWhen all songs are accounted for, then amplitude is ready\n\t\t\t\tto rock and we set the rest of the config.\n\t\t\t*/\n\t\t\tif( config.soundcloud_songs_ready == config.soundcloud_song_count ){\n\t\t\t\tAmplitudeInitializer.setConfig( tempUserConfig );\n\t\t\t}\n\t\t});\n\t}\n\n\t/*\n\t\tReturns the publically accessible methods\n\t*/\n\treturn {\n\t\tloadSoundCloud: loadSoundCloud\n\t}\n})();\n\nexport default AmplitudeSoundcloud\n\n\n\n// WEBPACK FOOTER //\n// ./src/soundcloud/soundcloud.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * These methods help sync visual displays. They essentially make the visual sync\n * methods smaller and more maintainable.\n *\n * @module visual/AmplitudeVisualSyncHelpers\n */\nlet AmplitudeVisualSyncHelpers = (function() {\n\t/**\n\t * Updates any elements that display the current hour for the song.\n\t *\n\t * @access public\n\t * @param {number} hours \t- An integer conaining how many hours into the song.\n\t */\n\tfunction syncCurrentHours( hours ){\n\t\t/*\n\t\t\tGets all of the song hour selectors.\n\t\t*/\n\t\tlet hourSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-current-hours[amplitude-main-current-hours=\"true\"]',\n\t\t\t\t'.amplitude-current-hours[amplitude-playlist-current-hours=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-current-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-current-hours[amplitude-main-current-hours=\"true\"]',\n\t\t\t\t'.amplitude-current-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tEnsures that there are some hour selectors.\n\t\t*/\n\t\tif( document.querySelectorAll( hourSelectors.join() ).length > 0 ){\n\t\t\t/*\n\t\t\t\tGet all of the hour selectors\n\t\t\t*/\n\t\t\tconst currentHourSelectors = document.querySelectorAll( hourSelectors.join() );\n\n\t\t\t/*\n\t\t\t\tSet the current hour selector's inner html to hours passed in.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < currentHourSelectors.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tIf the selector is a main selector, we set the hours.\n\t\t\t\t*/\n\t\t\t\tif( currentHourSelectors[i].getAttribute('amplitude-main-current-hours') == 'true' ){\n\t\t\t\t\tcurrentHourSelectors[i].innerHTML = hours;\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t\t&& currentHourSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\t\tcurrentHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\t\tdoes not have a playlist then we set the hours. This\n\t\t\t\t\t\tmeans that the current selector is an individual song\n\t\t\t\t\t\tselector.\n\t\t\t\t\t*/\n\t\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t\t&& !currentHourSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\t\tcurrentHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t\t*/\n\t\t\t\t\t}else{\n\t\t\t\t\t\tcurrentHourSelectors[i].innerHTML = '0';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tResets the current hours displays to 0\n\t--------------------------------------------------------------------------*/\n\tfunction resetCurrentHours(){\n\t\t/*\n\t\t\tGets the hour display elements\n\t\t*/\n\t\tlet hourSelectors = document.querySelectorAll('.amplitude-current-hours');\n\n\t\t/*\n\t\t\tIterates over all of the hour selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( var i = 0; i < hourSelectors.length; i++ ){\n\t\t\thourSelectors[i].innerHTML = '0';\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the current minutes for the song.\n\t *\n\t * @access public\n\t * @param {number} minutes \t- An integer conaining how many minutes into the song.\n\t */\n\tfunction syncCurrentMinutes( minutes ){\n\t\t/*\n\t\t\tGets all of the song minute selectors.\n\t\t*/\n\t\tlet minuteSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-current-minutes[amplitude-main-current-minutes=\"true\"]',\n\t\t\t\t'.amplitude-current-minutes[amplitude-playlist-current-minutes=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-current-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-current-minutes[amplitude-main-current-minutes=\"true\"]',\n\t\t\t\t'.amplitude-current-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tGrabs the current minute selectors\n\t\t*/\n const currentMinuteSelectors = document.querySelectorAll( minuteSelectors.join() );\n\n\t\t/*\n\t\t\tSet the current minute selector's inner html to minutes passed in.\n\t\t*/\n\t\tfor( let i = 0, l = currentMinuteSelectors.length; i < l; i++ ){\n\t\t\t/*\n\t\t\t\tIf the selector is a main selector, we set the seconds.\n\t\t\t*/\n\t\t\tif( currentMinuteSelectors[i].getAttribute('amplitude-main-current-minutes') == 'true' ){\n\t\t\t\tcurrentMinuteSelectors[i].innerHTML = minutes;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& currentMinuteSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\tcurrentMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\tdoes not have a playlist then we set the minutes. This\n\t\t\t\t\tmeans that the current selector is an individual song\n\t\t\t\t\tselector.\n\t\t\t\t*/\n\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t&& !currentMinuteSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tcurrentMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t*/\n\t\t\t\t}else{\n\t\t\t\t\tcurrentMinuteSelectors[i].innerHTML = '00';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Resets the current minutes displays to 00\n\t *\n\t * @access public\n\t */\n\tfunction resetCurrentMinutes(){\n\t\t/*\n\t\t\tGets the minutes display elements\n\t\t*/\n\t\tlet minuteSelectors = document.querySelectorAll('.amplitude-current-minutes');\n\n\t\t/*\n\t\t\tIterates over all of the minute selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( let i = 0; i < minuteSelectors.length; i++ ){\n\t\t\tminuteSelectors[i].innerHTML = '00';\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the current seconds for the song.\n\t *\n\t * @access public\n\t * @param {number} seconds\t- An integer conaining how many seconds into the song.\n\t */\n\tfunction syncCurrentSeconds( seconds ){\n\t\t/*\n\t\t\tGets all of the song second selectors. If the active playlist\n\t\t\tis not null, then we get the playlist selectors.\n\t\t*/\n\t\tlet secondSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-current-seconds[amplitude-main-current-seconds=\"true\"]',\n\t\t\t\t'.amplitude-current-seconds[amplitude-playlist-current-seconds=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-current-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-current-seconds[amplitude-main-current-seconds=\"true\"]',\n\t\t\t\t'.amplitude-current-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n /*\n \tGet all of the second selectors\n */\n const currentSecondSelectors = document.querySelectorAll( secondSelectors.join() );\n\n /*\n \tIterate over all of the second selectors.\n */\n for( let i = 0, l = currentSecondSelectors.length; i < l; i++ ){\n \t/*\n \t\tIf the selector is a main selector, we set the seconds.\n \t*/\n \tif( currentSecondSelectors[i].getAttribute('amplitude-main-current-seconds') == 'true' ){\n \t\tcurrentSecondSelectors[i].innerHTML = seconds;\n \t}else{\n \t\t/*\n \t\t\tIf the active playlist is not null or empty\n \t\t\tand the attribute of the playlist is equal to the\n \t\t\tactive playlist, then we set the inner html.\n \t\t*/\n \t\tif( config.active_playlist != ''\n \t\t\t&& config.active_playlist != null\n \t\t\t&& currentSecondSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n \t\t\t\tcurrentSecondSelectors[i].innerHTML = seconds;\n \t\t/*\n \t\t\tIf the active playlist is not set and the selector\n \t\t\tdoes not have a playlist then we set the seconds. This\n \t\t\tmeans that the current selector is an individual song\n \t\t\tselector.\n \t\t*/\n \t\t}else if( config.active_playlist == ''\n \t\t\t|| config.active_playlist == null\n \t\t\t&& !currentSecondSelectors[i].hasAttribute('amplitude-playlist') ){\n \t\t\t\tcurrentSecondSelectors[i].innerHTML = seconds;\n \t\t/*\n \t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n \t\t*/\n \t\t}else{\n \t\t\tcurrentSecondSelectors[i].innerHTML = '00';\n \t\t}\n \t}\n }\n\t}\n\n\t/**\n\t * Resets the current seconds displays to 00\n\t *\n\t * @access public\n\t */\n\tfunction resetCurrentSeconds(){\n\t\t/*\n\t\t\tGets the seconds display elements\n\t\t*/\n\t\tlet secondSelectors = document.querySelectorAll('.amplitude-current-seconds');\n\n\t\t/*\n\t\t\tIterates over all of the seconds selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( let i = 0; i < secondSelectors.length; i++ ){\n\t\t\tsecondSelectors[i].innerHTML = '00';\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the current time for the song. This\n\t * is a computed field that will be commonly used.\n\t *\n\t * @access public\n\t * @param {object} currentTime \t- A json object conaining the parts for the current time for the song.\n\t */\n\tfunction syncCurrentTime( currentTime ){\n\t\t/*\n\t\t\tGets all of the song time selectors.\n\t\t*/\n\t\tlet timeSelectors = [\n\t\t\t'.amplitude-current-time[amplitude-main-current-time=\"true\"]',\n\t\t\t'.amplitude-current-time[amplitude-playlist-main-current-time=\"'+config.active_playlist+'\"]',\n\t\t\t'.amplitude-current-time[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t];\n\n\t\t/*\n\t\t\tGet all of the time selectors.\n\t\t*/\n\t\tlet currentTimeSelectors = document.querySelectorAll( timeSelectors.join() );\n\n\t\t/*\n\t\t\tSet the time selector's inner html to the current time for the song. The current\n\t\t\ttime is computed by joining minutes and seconds.\n\t\t*/\n\t\tvar timeText = currentTime.minutes+':'+currentTime.seconds;\n\t\tif ( currentTime.hours > 0 ) {\n\t\t\ttimeText = currentTime.hours + ':' + timeText;\n\t\t}\n\t\tfor( let i = 0, l=currentTimeSelectors.length; i < l; i++ ){\n\t\t\tcurrentTimeSelectors[i].innerHTML = timeText;\n\t\t}\n\n\t}\n\n\t/**\n\t * Resets the current time displays to 00:00\n\t *\n\t * @access public\n\t */\n\tfunction resetCurrentTime(){\n\t\t/*\n\t\t\tGets the time selector display elements\n\t\t*/\n\t\tlet timeSelectors = document.querySelectorAll('.amplitude-current-time');\n\n\t\t/*\n\t\t\tIterates over all of the time selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( let i = 0; i < timeSelectors.length; i++ ){\n\t\t\ttimeSelectors[i].innerHTML = '00:00';\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the song played progress bars. These are HTML5 progress elements.\n\t *\n\t * @access private\n\t * @param {number} songPlayedPercentage \t- The percentage of the song that has been played.\n\t */\n\tfunction syncSongPlayedProgressBar( songPlayedPercentage ){\n\t\tsyncMainSongPlayedProgressBars( songPlayedPercentage );\n\t\tsyncPlaylistSongPlayedProgressBars( songPlayedPercentage );\n\t\tsyncIndividualSongPlayedProgressBars( songPlayedPercentage );\n\t}\n\n\t/**\n\t * Sync how much has been played with a progress bar. This is the main progress bar.\n\t *\n\t * @access private\n\t * @param {number} songPlayedPercentage \t- The percent of the song completed.\n\t */\n\tfunction syncMainSongPlayedProgressBars( songPlayedPercentage ){\n\t\t/*\n\t\t\tEnsure that the song completion percentage is a number\n\t\t*/\n\t\tif( !isNaN( songPlayedPercentage ) ){\n\t\t\t/*\n\t\t\t\tGet all of the song progress bars\n\t\t\t*/\n\t\t\tlet songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-main-song-played-progress=\"true\"]');\n\n\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\tlet max = songPlayedProgressBars[i].max;\n\n\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sync how much has been played with a progress bar. This is the playlist progress bar.\n\t *\n\t * @access public\n\t * @param {number} songPlayedPercentage \t- The percent of the song completed.\n\t */\n\tfunction syncPlaylistSongPlayedProgressBars( songPlayedPercentage ){\n\t\t/*\n\t\t\tEnsure that the song completion percentage is a number\n\t\t*/\n\t\tif( !isNaN( songPlayedPercentage ) ){\n\t\t\t/*\n\t\t\t\tGet all of the song progress bars\n\t\t\t*/\n\t\t\tlet songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-playlist-song-played-progress=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]');\n\n\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\tlet max = songPlayedProgressBars[i].max;\n\n\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sync how much has been played with a progress bar. This is for an individual song.\n\t *\n\t * @access private\n\t * @param {number} songPlayedPercentage \t- The percent of the song completed.\n\t */\n\tfunction syncIndividualSongPlayedProgressBars( songPlayedPercentage ){\n\t\t/*\n\t\t\tEnsure that the song completion percentage is a number\n\t\t*/\n\t\tif( !isNaN( songPlayedPercentage ) ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is not null, we get the individual song\n\t\t\t\tplayed progress for the playlist.\n\t\t\t*/\n\t\t\tif( config.active_playlist != '' && config.active_playlist != null ){\n\t\t\t\t/*\n\t\t\t\t\tGet all of the song progress bars\n\t\t\t\t*/\n\t\t\t let songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-playlist=\"'+config.active_playlist+'\"][amplitude-song-index=\"'+config.active_index+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\t let max = songPlayedProgressBars[i].max;\n\n\t\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGet all of the song progress bars\n\t\t\t\t*/\n\t\t\t\tlet songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-song-index=\"'+config.active_index+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\t\tlet max = songPlayedProgressBars[i].max;\n\n\t\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets an element to be playing by removing the 'amplitude-paused' class\n\t * and adding the 'amplitude-playing' class\n\t *\n\t * @access public\n\t * @param {element} element \t- The element getting the playing class added.\n\t */\n\tfunction setElementPlay( element ){\n\t\telement.classList.add('amplitude-playing');\n\t\telement.classList.remove('amplitude-paused');\n\t}\n\n\t/**\n\t * Sets an element to be paused by adding the 'amplitude-paused' class\n\t * and removing the 'amplitude-playing' class\n\t *\n\t * @access public\n\t * @param {element} element \t- The element getting the paused class added.\n\t */\n\tfunction setElementPause( element ){\n\t\telement.classList.remove('amplitude-playing');\n\t\telement.classList.add('amplitude-paused');\n\t}\n\n\t/**\n\t * Updates any elements that display the duration hour for the song.\n\t *\n\t * @access public\n\t * @param {number} hours \t\t- An integer conaining how many hours are in the song\n\t */\n\tfunction syncDurationHours( hours ){\n\t\t/*\n\t\t\tGets all of the song hour selectors.\n\t\t*/\n\t\tlet hourSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-duration-hours[amplitude-main-duration-hours=\"true\"]',\n\t\t\t\t'.amplitude-duration-hours[amplitude-playlist-duration-hours=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-duration-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-duration-hours[amplitude-main-duration-hours=\"true\"]',\n\t\t\t\t'.amplitude-duration-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tEnsures that there are some hour selectors.\n\t\t*/\n\t\tif( document.querySelectorAll( hourSelectors.join() ).length > 0 ){\n\t\t\t/*\n\t\t\t\tGet all of the hour selectors\n\t\t\t*/\n\t\t\tlet durationHourSelectors = document.querySelectorAll( hourSelectors.join() );\n\n\t\t\t/*\n\t\t\t\tSet the duration hour selector's inner html to hours passed in.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < durationHourSelectors.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tIf the selector is a main selector, we set the hours.\n\t\t\t\t*/\n\t\t\t\tif( durationHourSelectors[i].getAttribute('amplitude-main-duration-hours') == 'true' ){\n\t\t\t\t\tdurationHourSelectors[i].innerHTML = hours;\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t\t&& durationHourSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\t\tdurationHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\t\tdoes not have a playlist then we set the hours. This\n\t\t\t\t\t\tmeans that the duration selector is an individual song\n\t\t\t\t\t\tselector.\n\t\t\t\t\t*/\n\t\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t\t&& !durationHourSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\t\tdurationHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t\t*/\n\t\t\t\t\t}else{\n\t\t\t\t\t\tdurationHourSelectors[i].innerHTML = '0';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the duration minutes for the song.\n\t *\n\t * @access public\n\t * @param {number} minutes \t- An integer conaining how many minutes into the song.\n\t */\n\tfunction syncDurationMinutes( minutes ){\n\t\t/*\n\t\t\tGets all of the song minute selectors.\n\t\t*/\n\t\tlet minuteSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-duration-minutes[amplitude-main-duration-minutes=\"true\"]',\n\t\t\t\t'.amplitude-duration-minutes[amplitude-playlist-duration-minutes=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-duration-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-duration-minutes[amplitude-main-duration-minutes=\"true\"]',\n\t\t\t\t'.amplitude-duration-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tGet all of the minute selectors\n\t\t*/\n\t\tlet durationMinuteSelectors = document.querySelectorAll( minuteSelectors.join() );\n\n\t\t/*\n\t\t\tSet the duration minute selector's inner html to minutes passed in.\n\t\t*/\n\t\tfor( let i = 0; i < durationMinuteSelectors.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the selector is a main selector, we set the seconds.\n\t\t\t*/\n\t\t\tif( durationMinuteSelectors[i].getAttribute('amplitude-main-duration-minutes') == 'true' ){\n\t\t\t\tdurationMinuteSelectors[i].innerHTML = minutes;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& durationMinuteSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\tdurationMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\tdoes not have a playlist then we set the minutes. This\n\t\t\t\t\tmeans that the duration selector is an individual song\n\t\t\t\t\tselector.\n\t\t\t\t*/\n\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t&& !durationMinuteSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tdurationMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t*/\n\t\t\t\t}else{\n\t\t\t\t\tdurationMinuteSelectors[i].innerHTML = '00';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates any elements that display the duration seconds for the song.\n\t *\n\t * @access private\n\t * @param {number} seconds \t- An integer conaining how many seconds into the song.\n\t */\n\tfunction syncDurationSeconds( seconds ){\n\t\t/*\n\t\t\tGets all of the song second selectors. If the active playlist\n\t\t\tis not null, then we get the playlist selectors.\n\t\t*/\n\t\tlet secondSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-duration-seconds[amplitude-main-duration-seconds=\"true\"]',\n\t\t\t\t'.amplitude-duration-seconds[amplitude-playlist-duration-seconds=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-duration-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-duration-seconds[amplitude-main-duration-seconds=\"true\"]',\n\t\t\t\t'.amplitude-duration-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tGet all of the second selectors\n\t\t*/\n\t\tlet durationSecondSelectors = document.querySelectorAll( secondSelectors.join() );\n\n\t\t/*\n\t\t\tIterate over all of the second selectors.\n\t\t*/\n\t\tfor( let i = 0; i < durationSecondSelectors.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the selector is a main selector, we set the seconds.\n\t\t\t*/\n\t\t\tif( durationSecondSelectors[i].getAttribute('amplitude-main-duration-seconds') == 'true' ){\n\t\t\t\tdurationSecondSelectors[i].innerHTML = seconds;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& durationSecondSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\tdurationSecondSelectors[i].innerHTML = seconds;\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\tdoes not have a playlist then we set the seconds. This\n\t\t\t\t\tmeans that the duration selector is an individual song\n\t\t\t\t\tselector.\n\t\t\t\t*/\n\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t&& !durationSecondSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tdurationSecondSelectors[i].innerHTML = seconds;\n\t\t\t\t/*\n\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t*/\n\t\t\t\t}else{\n\t\t\t\t\tdurationSecondSelectors[i].innerHTML = '00';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the duration time for the song. This\n\t * is a computed field that will be commonly used.\n\t *\n\t * @access public\n\t * @param {object} durationTime \t- A json object conaining the parts for the duration time for the song.\n\t */\n\tfunction syncDurationTime( durationTime ){\n\t\t/*\n\t\t\tGets all of the song time selectors.\n\t\t*/\n\t\tlet timeSelectors = [\n\t\t\t'.amplitude-duration-time[amplitude-main-duration-time=\"true\"]',\n\t\t\t'.amplitude-duration-time[amplitude-playlist-main-duration-time=\"'+config.active_playlist+'\"]',\n\t\t\t'.amplitude-duration-time[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t];\n\n\t\t/*\n\t\t\tGet all of the time selectors.\n\t\t*/\n\t\tlet durationTimeSelectors = document.querySelectorAll( timeSelectors.join() );\n\n\t\t/*\n\t\t\tSet the time selector's inner html to the duration time for the song. The duration\n\t\t\ttime is computed by joining minutes and seconds.\n\t\t*/\n\t\tvar durationText = '00:00';\n\t\tif( !isNaN( durationTime.minutes ) && !isNaN( durationTime.seconds ) ){\n\t\t\tdurationText = durationTime.minutes+':'+durationTime.seconds;\n\t\t\tif( !isNaN( durationTime.hours ) && durationTime.hours > 0 ){\n\t\t\t\tdurationText = durationTime.hours+':'+durationText;\n\t\t\t}\n\t\t}\n\t\tfor( var i = 0; i < durationTimeSelectors.length; i++ ){\n\t\t\tdurationTimeSelectors[i].innerHTML = durationText;\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates the elements that show how much time is remaining in the song.\n\t *\n\t * @access public\n\t * @param {object} currentTime \t- A json object containing the parts for the current time for the song.\n\t * @param {object} durationTime - A json object conaining the parts for the duration time for the song.\n\t */\n\tfunction syncCountDownTime( currentTime, songDuration ){\n\t\t/*\n\t\t\tInitialize time remaining.\n\t\t*/\n\t\tlet timeRemaining = '00:00';\n\n\t\t/*\n\t\t\tEnsure that all values are defined.\n\t\t*/\n\t\tif( currentTime != undefined && songDuration != undefined ){\n\t\t\t/*\n\t\t\t\tInitialize the total current seconds and total duration seconds\n\t\t\t*/\n\t\t\tlet totalCurrentSeconds = parseInt( currentTime.seconds ) + ( parseInt( currentTime.minutes ) * 60 ) + ( ( parseInt( currentTime.hours ) * 60 * 60 ) );\n\t\t\tlet totalDurationSeconds = parseInt( songDuration.seconds ) + ( parseInt( songDuration.minutes ) * 60 ) + ( ( parseInt( songDuration.hours ) * 60 * 60 ) );\n\n\t\t\t/*\n\t\t\t\tIf the two variables are numbers we continue the computing.\n\t\t\t*/\n\t\t\tif( !isNaN( totalCurrentSeconds ) && !isNaN( totalDurationSeconds ) ){\n\t\t\t\t/*\n\t\t\t\t\tFind the total remaining seconds.\n\t\t\t\t*/\n\t\t\t\tlet timeRemainingTotalSeconds = totalDurationSeconds - totalCurrentSeconds;\n\n\t\t\t\tvar remainingHours = Math.floor(timeRemainingTotalSeconds / 3600);\n\t\t\t\tvar remainingMinutes = Math.floor((timeRemainingTotalSeconds - (remainingHours * 3600)) / 60);\n\t\t\t\tvar remainingSeconds = timeRemainingTotalSeconds - (remainingHours * 3600) - (remainingMinutes * 60);\n\n\t\t\t\ttimeRemaining = (remainingMinutes < 10 ? '0' + remainingMinutes : remainingMinutes) + ':' +\n\t\t\t\t\t(remainingSeconds < 10 ? '0' + remainingSeconds : remainingSeconds);\n\n\t\t\t\tif(remainingHours > 0) {\n\t\t\t\t\ttimeRemaining = remainingHours + ':' + timeRemaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tGets all of the song time selectors.\n\t\t*/\n\t let timeSelectors = [\n\t\t\t'.amplitude-time-remaining[amplitude-main-time-remaining=\"true\"]',\n\t\t\t'.amplitude-time-remaining[amplitude-playlist-main-time-remaining=\"'+config.active_playlist+'\"]',\n\t\t\t'.amplitude-time-remaining[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t];\n\n\t\t/*\n\t\t\tGet all of the time selectors.\n\t\t*/\n\t let timeRemainingSelectors = document.querySelectorAll( timeSelectors.join() );\n\n\t\t/*\n\t\t\tSet the time selector's inner html to the duration time for the song. The duration\n\t\t\ttime is computed by joining minutes and seconds.\n\t\t*/\n\t\tfor( let i = 0; i < timeRemainingSelectors.length; i++ ){\n\t\t\ttimeRemainingSelectors[i].innerHTML = timeRemaining;\n\t\t}\n\t}\n\n\t/*\n\t\tReturn the publically available functions.\n\t*/\n\treturn {\n\t\tsyncCurrentHours: syncCurrentHours,\n\t\tsyncCurrentMinutes: syncCurrentMinutes,\n\t\tsyncCurrentSeconds: syncCurrentSeconds,\n\t\tsyncCurrentTime: syncCurrentTime,\n\t\tresetCurrentHours: resetCurrentHours,\n\t\tresetCurrentMinutes: resetCurrentMinutes,\n\t\tresetCurrentSeconds: resetCurrentSeconds,\n\t\tresetCurrentTime: resetCurrentTime,\n\t\tsyncSongPlayedProgressBar: syncSongPlayedProgressBar,\n\t\tsetElementPlay: setElementPlay,\n\t\tsetElementPause: setElementPause,\n\t\tsyncDurationHours: syncDurationHours,\n\t\tsyncDurationMinutes: syncDurationMinutes,\n\t\tsyncDurationSeconds: syncDurationSeconds,\n\t\tsyncDurationTime: syncDurationTime,\n\t\tsyncCountDownTime: syncCountDownTime\n\t}\n})();\n\nexport default AmplitudeVisualSyncHelpers\n\n\n\n// WEBPACK FOOTER //\n// ./src/visual/helpers.js"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 85736e28a982b867907b","webpack:///./src/config.js","webpack:///./src/core/helpers.js","webpack:///./src/visual/visual.js","webpack:///./src/core/core.js","webpack:///./src/events/events.js","webpack:///./src/events/helpers.js","webpack:///./src/init/init.js","webpack:///./src/events/handlers.js","webpack:///./src/index.js","webpack:///./src/soundcloud/soundcloud.js","webpack:///./src/visual/helpers.js"],"names":["module","exports","version","active_song","Audio","active_metadata","active_album","active_index","active_playlist","autoplay","playback_speed","callbacks","songs","playlists","start_song","shuffled_playlists","starting_playlist","starting_playlist_song","shuffled_statuses","shuffled_active_indexes","repeat_statuses","repeat","repeat_song","shuffle_list","shuffle_on","shuffle_active_index","default_album_art","debug","volume","pre_mute_volume","volume_increment","volume_decrement","soundcloud_client","soundcloud_use_art","soundcloud_song_count","soundcloud_songs_ready","is_touch_moving","buffered","bindings","continue_next","AmplitudeHelpers","resetConfig","handle_song_elements","writeDebugMessage","message","console","log","runCallback","callbackName","callbackFunction","error","changeSong","songIndex","song","stop","setPlayPauseButtonsToPause","resetSongSliders","resetSongPlayedProgressBars","resetTimes","checkNewAlbum","setNewSong","displaySongMetadata","setActiveContainer","syncSongDuration","checkNewSong","newAlbum","checkNewPlaylist","playlist","index","src","url","album","shuffleSongs","shuffleTemp","Array","length","i","original_index","randNum","Math","floor","random","shuffleSwap","shufflePlaylistSongs","shuffleList","original","temp","setActivePlaylist","isURL","pattern","test","isInt","int","isNaN","parseInt","Number","AmplitudeVisualSync","syncCurrentTime","currentTime","completionPercentage","syncCurrentHours","hours","syncCurrentMinutes","minutes","syncCurrentSeconds","seconds","syncMainSliderLocation","syncPlaylistSliderLocation","syncSongSliderLocation","syncSongPlayedProgressBar","resetCurrentHours","resetCurrentMinutes","resetCurrentSeconds","resetCurrentTime","songSliders","document","getElementsByClassName","value","resetSongBufferedProgressBars","songBufferedProgressBars","songPlayedProgressBars","songContainers","classList","remove","querySelectorAll","hasAttribute","add","imageMetaDataKeys","ignoredKeys","songInfoElements","info","getAttribute","main","undefined","indexOf","setAttribute","innerHTML","setFirstSongInPlaylist","elementPlaylist","syncPlaybackSpeed","playbackSpeedClasses","syncBufferedProgressBars","parseFloat","syncVolumeSliders","amplitudeVolumeSliders","playPauseElements","setElementPause","syncMainPlayPause","state","paused","setElementPlay","syncPlaylistPlayPause","playlistPlayPauseElements","syncSongPlayPause","songPlayPauseElements","syncRepeat","repeatClasses","syncRepeatPlaylist","repeatButtons","syncRepeatSong","repeatSongClasses","syncMute","muteClasses","syncShuffle","shuffleButtons","syncPlaylistShuffle","location","mainSongSliders","playlistSongSliders","syncVolumeSliderLocation","volumeSliders","songDuration","syncDurationHours","syncDurationMinutes","syncDurationSeconds","syncDurationTime","syncCountDownTime","syncSongsMetaData","AmplitudeCore","play","live","reconnectStream","navigator","userAgent","playbackRate","pause","disconnectStream","setVolume","volumeLevel","setSongLocation","songPercentage","duration","song_percentage","skipToLocation","addEventListener","once","load","playNow","playSongAtIndex","playPlaylistSongAtIndex","setPlaybackSpeed","playbackSpeed","AmplitudeEvents","initializeEvents","bindTimeUpdate","bindKeyDownEventHandlers","bindSongEnded","bindProgress","bindPlay","bindPause","bindPlayPause","bindStop","bindMute","bindVolumeUp","bindVolumeDown","bindSongSlider","bindVolumeSlider","bindNext","bindPrev","bindShuffle","bindRepeat","bindPlaybackSpeed","bindSkipTo","removeEventListener","updateTime","keydown","songEnded","progess","progress","play_classes","pause_classes","play_pause_classes","playPause","stop_classes","mute_classes","mute","volume_up_classes","volumeUp","volume_down_classes","volumeDown","ua","window","msie","song_sliders","match","songSlider","volume_sliders","volumeSlider","next_classes","next","prev_classes","prev","shuffle_classes","shuffle","repeat_classes","playback_speed_classes","skipToClasses","skipTo","AmplitudeEventsHelpers","computeCurrentTimes","currentSeconds","currentMinutes","currentHours","computeSongDuration","songDurationSeconds","songDurationMinutes","songDurationHours","computeSongCompletionPercentage","speed","setRepeat","setRepeatSong","setMainPlayPause","setPlaylistPlayPause","setSongPlayPause","setShuffle","setNext","nextIndex","endOfList","setNextPlaylist","shuffledPlaylistActiveSongIndex","playlistActiveSongIndex","setPrev","prevIndex","setPrevPlaylist","runKeyEvent","key","AmplitudesEventHelpers","AmplitudeEvenstHelpers","AmplitudeInitializer","initialize","userConfig","ready","countPlaylists","initializeDefaultLiveSettings","checkValidSongsInPlaylists","initializePlaylistShuffleStatuses","initializePlaylistsRepeatStatuses","initializePlaylistShuffleLists","initializePlaylistShuffleIndexes","initializeFirstSongInPlaylistMetaData","tempUserConfig","loadSoundCloud","setConfig","rebindDisplay","preload","size","hasOwnProperty","bufferedEnd","end","songCompletionPercentage","event","which","playButtonSongIndex","playButtonPlaylistIndex","pauseButtonSongIndex","pauseButtonPlaylistIndex","muted","locationPercentage","isFinite","repeatSong","Amplitude","init","bindNewElements","getActivePlaylist","getPlaybackSpeed","getRepeat","getShuffle","getShufflePlaylist","setShufflePlaylist","playlistKey","getDefaultAlbumArt","setDefaultAlbumArt","getSongPlayedPercentage","setSongPlayedPercentage","percentage","setDebug","getActiveSongMetadata","getSongByIndex","getSongAtPlaylistIndex","addSong","push","addSongToPlaylist","removeSong","splice","removeSongFromPlaylist","getAudio","getSongs","getSongsInPlaylist","songsArray","getSongsState","getSongsStatePlaylist","shuffled_status","getActiveIndex","getActiveIndexState","getVersion","getBuffered","audio","AmplitudeSoundcloud","head","getElementsByTagName","script","createElement","type","onreadystatechange","initSoundcloud","onload","appendChild","SC","client_id","getStreamableURLs","soundcloud_regex","resolveStreamable","get","sound","streamable","stream_url","cover_art_url","artwork_url","soundcloud_data","name","artist","AmplitudeVisualSyncHelpers","hourSelectors","join","currentHourSelectors","minuteSelectors","currentMinuteSelectors","l","secondSelectors","currentSecondSelectors","timeSelectors","currentTimeSelectors","timeText","songPlayedPercentage","syncMainSongPlayedProgressBars","syncPlaylistSongPlayedProgressBars","syncIndividualSongPlayedProgressBars","max","element","durationHourSelectors","durationMinuteSelectors","durationSecondSelectors","durationTime","durationTimeSelectors","durationText","timeRemaining","totalCurrentSeconds","totalDurationSeconds","timeRemainingTotalSeconds","remainingHours","remainingMinutes","remainingSeconds","timeRemainingSelectors"],"mappings":"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","file":"amplitude.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"Amplitude\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Amplitude\"] = factory();\n\telse\n\t\troot[\"Amplitude\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 8);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 85736e28a982b867907b","/**\n * These variables make Amplitude run. The config is the most important\n * containing active settings and parameters.\n *\n * The config JSON is the global settings for ALL of Amplitude functions.\n * This is global and contains all of the user preferences. The default\n * settings are set, and the user overwrites them when they initialize\n * Amplitude.\n *\n * @module config\n * @type {object}\n * @property {string} \tconfig.version \t\t\t\t- The current version of AmplitudeJS.\n * @property {object} \tconfig.active_song \t\t \t\t\t\t\t-\tHandles all of the audio.\n * @property {object} \tconfig.active_metadata\t\t\t\t\t- Contains the active metadata for the song.\n * @property {string} \tconfig.active_album\t\t\t\t\t\t\t- Holds the active album name. Used to check and see if the album changed and run the album changed callback.\n * @property {number} \tconfig.active_index\t\t\t\t\t\t\t- Contains the index of the actively playing song.\n * @property {string} \tconfig.active_playlist\t\t\t\t\t- Contains the key to the active playlist index.\n * @property {boolean}\tconfig.autoplay\t\t\t\t\t\t\t\t\t- Set to true to autoplay the song\n * @property {number} \tconfig.playback_speed\t\t\t\t\t\t- Sets the initial playback speed of the song. The values for this can be 1.0, 1.5, 2.0\n * @property {object} \tconfig.callbacks\t\t\t\t\t\t\t\t- The user can pass a JSON object with a key => value store of callbacks to be run at certain events.\n * @property {array} \t\tconfig.songs\t\t\t\t\t\t\t\t\t\t- Contains all of the songs the user has passed to Amplitude to use.\n * @property {object} \tconfig.playlists\t\t\t\t\t\t\t\t- Contains all of the playlists the user created.\n * @property {object} \tconfig.start_song \t\t\t\t\t\t\t- The index of the song that AmplitudeJS should start with.\n * @property {object} \tconfig.shuffled_playlists\t\t\t\t- Will contain shuffled playlists.\n * @property {string} \tconfig.starting_playlist \t\t\t\t- The starting playlist the player will intiialize to.\n * @property {string} \tconfig.starting_playlist_song \t- The index of the song in the playlist that should be started.\n * @property {object} \tconfig.shuffled_statuses \t\t\t\t- Contains whether the current playlist is in shuffle mode or not.\n * @property {object} \tconfig.repeat_statuses \t\t\t\t\t- Contains whether the playlist is in repeat mode or not.\n * @property {object} \tconfig.shuffled_active_indexes\t- Contains the active index in a shuffled playlist.\n * @property {boolean} \tconfig.repeat \t\t\t\t\t\t\t\t\t- When repeat is on, when the song ends the song will replay itself.\n * @property {object} \tconfig.shuffle_list\t\t\t\t\t\t\t- When shuffled, gets populated with the songs the user provided in a random order.\n * @property {boolean} \tconfig.shuffle_on\t\t\t\t\t\t\t\t- When on, gets set to true so when traversing through songs, AmplitudeJS knows whether or not to use the songs object or the shuffle_list\n * @property {number} \tconfig.shuffle_active_index \t\t- When shuffled, this index is used to let AmplitudeJS know where it's at when traversing.\n * @property {string}\t\tconfig.default_album_art \t\t\t\t- The user can set default album art to be displayed if the song they set doesn't contain album art.\n * @property {boolean} \tconfig.debug\t\t\t\t\t\t\t\t\t\t- When set to true, AmplitudeJS will print to the console any errors providing helpful feedback to the user.\n * @property {number} \tconfig.volume \t\t\t\t\t\t\t\t\t- The user can set the initial volume to a number between 0 and 1 over-riding the default of .5\n * @property {number} \tconfig.pre_mute_volume \t\t\t\t\t- This is set on mute so that when a user un-mutes AmplitudeJS knows what to restore the volume to.\n * @property {number}\t\tconfig.volume_increment \t\t\t\t- The default values are an integer between 1 and 100 for how much the volume should increase when the user presses the volume up button.\n * @property {number}\t\tconfig.volume_decrement \t\t\t\t- The default values are an integer between 1 and 100 for how much the volume should decrease when the user presses the volume down button.\n * @property {string} \tconfig.soundcloud_client \t\t\t\t- When using SoundCloud, the user will have to provide their API Client ID\n * @property {boolean} \tconfig.soundcloud_use_art \t\t\t- The user can set this to true and AmplitudeJS will use the album art for the song returned from the Soundcloud API\n * @property {number} \tconfig.soundcloud_song_count \t\t- Used on config to count how many songs are from Soundcloud and compare it to how many are ready for when to move to the rest of the configuration\n * @property {number} \tconfig.soundcloud_songs_ready \t- Used on config to count how many songs are ready so when we get all of the data from the SoundCloud API that we need this should match the SoundCloud song count meaning we can move to the rest of the config.\n * @property {integer}\tconfig.is_touch_moving \t\t\t\t\t- Flag for if the user is moving the screen.\n * @property {boolean}\tconfig.buffered\t\t\t\t\t\t\t\t\t- How much of the song is buffered.\n * @property {object} \tconfig.bindings\t\t\t\t\t\t\t\t\t- Array of bindings to certain key events.\n * @property {boolean} \tconfig.continue_next \t\t\t\t\t\t- Determines when a song ends, we should continue to the next song.\n */\nmodule.exports = {\n\tversion: '3.3.0',\n\n\tactive_song: new Audio(),\n\n\tactive_metadata: {},\n\n\tactive_album: '',\n\n\tactive_index: 0,\n\n\tactive_playlist: '',\n\n\tautoplay: false,\n\n\tplayback_speed: 1.0,\n\n\tcallbacks: {},\n\n\tsongs: [],\n\n\tplaylists: {},\n\n\tstart_song: '',\n\n\tshuffled_playlists: {},\n\n\tstarting_playlist: '',\n\n\tstarting_playlist_song: '',\n\n\tshuffled_statuses: {},\n\n\tshuffled_active_indexes: {},\n\n\trepeat_statuses: {},\n\n\trepeat: false,\n\n\trepeat_song: false,\n\n\tshuffle_list: {},\n\n\tshuffle_on: false,\n\n\tshuffle_active_index: 0,\n\n\tdefault_album_art: '',\n\n\tdebug: false,\n\n\tvolume: .5,\n\n\tpre_mute_volume: .5,\n\n\tvolume_increment: 5,\n\n\tvolume_decrement: 5,\n\n\tsoundcloud_client: '',\n\n\tsoundcloud_use_art: false,\n\n\tsoundcloud_song_count: 0,\n\n\tsoundcloud_songs_ready: 0,\n\n\tis_touch_moving: false,\n\n\tbuffered: 0,\n\n\tbindings: {},\n\n\tcontinue_next: true\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/config.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * AmplitudeJS Core Module\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * AmplitudeJS Visual Sync\n * @module visual/AmplitudeVisualSync\n*/\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * For the sake of code clarity, these functions perform helper tasks\n * assisting the logical functions with what they need such as setting\n * the proper song index after an event has occured.\n *\n * @module core/AmplitudeHelpers\n */\nlet AmplitudeHelpers = (function () {\n\t/**\n\t * Resets the config to the default state. This is called on initialize\n\t * to ensure the user's config is what matters.\n\t *\n\t * Public Accessor: AmplitudeHelpers.resetConfig()\n\t *\n\t * @access public\n\t */\n\tfunction resetConfig(){\n\t\tconfig.active_song \t\t\t\t\t\t\t= new Audio();\n\t\tconfig.active_metadata \t\t\t\t\t= {};\n\t\tconfig.active_album \t\t\t\t\t\t= '';\n\t\tconfig.active_index \t\t\t\t\t\t= 0;\n\t\tconfig.active_playlist \t\t\t\t\t= '';\n\t\tconfig.active_playlist \t\t\t\t\t= '';\n\t\tconfig.autoplay \t\t\t\t\t\t\t\t= false;\n\t\tconfig.playback_speed \t\t\t\t\t= 1.0;\n\t\tconfig.callbacks \t\t\t\t\t\t\t\t= {};\n\t\tconfig.songs \t\t\t\t\t\t\t\t\t\t= [];\n\t\tconfig.playlists \t\t\t\t\t\t\t\t= {};\n\t\tconfig.start_song \t\t\t\t\t\t\t= '';\n\t\tconfig.shuffled_playlists \t\t\t= {};\n\t\tconfig.starting_playlist \t\t\t\t= '';\n\t\tconfig.starting_playlist_song \t= '';\n\t\tconfig.shuffled_statuses \t\t\t\t= {};\n\t\tconfig.repeat \t\t\t\t\t\t\t\t\t= false;\n\t\tconfig.shuffle_list \t\t\t\t\t\t= {};\n\t\tconfig.shuffle_on \t\t\t\t\t\t\t= false;\n\t\tconfig.shuffle_active_index \t\t= 0;\n\t\tconfig.default_album_art \t\t\t\t= '';\n\t\tconfig.debug \t\t\t\t\t\t\t\t\t\t= false;\n\t\tconfig.handle_song_elements \t\t= true;\n\t\tconfig.volume \t\t\t\t\t\t\t\t\t= .5;\n\t\tconfig.pre_mute_volume \t\t\t\t\t= .5;\n\t\tconfig.volume_increment \t\t\t\t= 5;\n\t\tconfig.volume_decrement \t\t\t\t= 5;\n\t\tconfig.soundcloud_client \t\t\t\t= '';\n\t\tconfig.soundcloud_use_art \t\t\t= false;\n\t\tconfig.soundcloud_song_count \t\t= 0;\n\t\tconfig.soundcloud_songs_ready \t= 0;\n\t\tconfig.continue_next \t\t\t\t\t\t= true;\n\t}\n\n\t/**\n\t * Writes out debug message to the console if enabled.\n\t *\n\t * Public Accessor: AmplitudeHelpers.writeDebugMessage( message )\n\t *\n\t * @access public\n\t * @param {string} message - The string that gets printed to alert the user of a debugging error.\n\t */\n\tfunction writeDebugMessage( message ){\n\t\tif( config.debug ){\n\t\t\tconsole.log( message );\n\t\t}\n\t}\n\n\t/**\n\t * Runs a user defined callback method\n\t *\n\t * Public Accessor: AmplitudeHelpers.runCallback( callbackName )\n\t *\n\t * @access public\n\t * @param {string} callbackName - The name of the callback we are going to run.\n\t */\n\tfunction runCallback( callbackName ){\n\t\t/*\n\t\t\tChecks to see if a user defined a callback method for the\n\t\t\tcallback we are running.\n\t\t*/\n\t\tif( config.callbacks[callbackName] ){\n\t\t\t/*\n\t\t\t\tBuild the callback function\n\t\t\t*/\n\t\t\tlet callbackFunction = config.callbacks[ callbackName ];\n\n\t\t\t/*\n\t\t\t\tWrite a debug message stating the callback we are running\n\t\t\t*/\n\t\t\twriteDebugMessage( 'Running Callback: '+callbackName );\n\n\t\t\t/*\n\t\t\t\tRun the callback function and catch any errors\n\t\t\t*/\n try {\n callbackFunction();\n }catch( error ) {\n if( error.message == \"CANCEL EVENT\" ){\n throw error;\n }else{\n writeDebugMessage( 'Callback error: '+error.message );\n\t\t\t\t}\n }\n\t\t}\n\t}\n\n\t/**\n\t * Changes the active song in the config. This happens in multiple\n\t * scenarios: The user clicks a play button that has an index that is\n\t * different than what is currently playing, the song ends and the next\n\t * song begins, etc.\n\t *\n\t * Public Accessor: AmplitudeHelpers.changeSong( songIndex )\n\t *\n\t * @access public\n\t * @param {number} songIndex - The song index we are changing to\n\t *\n\t */\n\tfunction changeSong( songIndex ){\n\t\t/*\n\t\t\tGrab the song at the index defined by the user.\n\t\t*/\n\t\tlet song = config.songs[ songIndex ];\n\n\t\t/*\n\t\t\tStops the currently playing song so we can adjust\n\t\t\twhat we need.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/**\n\t\t * @todo: Stop Visualization\n\t\t */\n\n\t\t/*\n\t\t\tSet all play buttons to pause while we change\n\t\t\tthe song.\n\t\t*/\n\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t/*\n\t\t\tSince it is a new song, we reset the song sliders. These\n\t\t\treact to time updates and will eventually be updated but we\n\t\t\tforce update them is if there is a song slider bound to a\n\t\t\tspecific song, they won't update.\n\t\t*/\n\t\tAmplitudeVisualSync.resetSongSliders();\n\n\t\t/*\n\t\t\tResets the progress bars\n\t\t*/\n\t\tAmplitudeVisualSync.resetSongPlayedProgressBars();\n\n\t\t/*\n\t\t\tReset all the time place holders accordingly.\n\t\t*/\n\t\tAmplitudeVisualSync.resetTimes();\n\n\t\t/*\n\t\t\tRun a callback if an album is going\n\t\t\tto change.\n\t\t*/\n\t\tif( checkNewAlbum( song ) ){\n\t\t\trunCallback('album_change');\n\t\t}\n\n\t\t/*\n\t\t\tSet the new song information so we can use the\n\t\t\tactive meta data later on.\n\t\t*/\n\t\tsetNewSong( song, songIndex );\n\n\t\t/*\n\t\t\tDisplay the new visual metadata now that the config has\n\t\t\tbeen changed. This will show the new song.\n\t\t*/\n\t\tAmplitudeVisualSync.displaySongMetadata();\n\n\t\t/*\n\t\t\tSets the active container. This is a class that\n\t\t\tdesigners can use on an element that contains the current\n\t\t\tsong's controls to show it's highlighted.\n\t\t*/\n\t\tAmplitudeVisualSync.setActiveContainer();\n\n\t\t/*\n\t\t\tSets the active song's duration\n\t\t*/\n\t\tAmplitudeVisualSync.syncSongDuration();\n\n\t\t/*\n\t\t\tRun song change callback.\n\t\t*/\n\t\trunCallback('song_change');\n\t}\n\n\t/**\n\t * Checks to see if the new song to be played is different than the song\n\t * that is currently playing. To be true, the user would have selected\n\t * play on a new song with a new index. To be false, the user would have\n\t * clicked play/pause on the song that was playing.\n\t *\n\t * Public Accessor: AmplitudeHelpers.checkNewSong( songIndex )\n\t *\n\t * @access public\n\t * @param {number} songIndex - The index of the new song to be played.\n\t * @returns {boolean} True if we are setting a new song, false if we are not setting a new song.\n\t */\n\tfunction checkNewSong( songIndex ){\n\t\tif( songIndex != config.active_index ){\n\t\t\treturn true;\n\t\t}else{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Checks to see if there is a new album\n\t *\n\t * Public Accessor: AmplitudeHelpers.checkNewAlbum( new Album )\n\t *\n\t * @access public\n\t * @param {string} newAlbum - Checks to see if the new song will have a new album.\n\t * @returns {boolean} True if there is a new album, false if there is not a new ablum.\n\t */\n\tfunction checkNewAlbum( newAlbum ){\n\t\tif( config.active_album != newAlbum ){\n\t\t\treturn true;\n\t\t}else{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Checks to see if there is a new playlist\n\t *\n\t * Public Accessor: AmplitudeHelpers.checkNewPlaylist( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist - The playlist passed in to check against the active playlist.\n\t * @returns {boolean} True if there is a new playlist, false if there is not a new playlist.\n\t */\n\tfunction checkNewPlaylist( playlist ){\n\t\tif( config.active_playlist != playlist ){\n\t\t\treturn true;\n\t\t}else{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Sets the new song in the config. Sets the src of the audio object,\n\t * updates the\tmetadata and sets the active album.\n\t *\n\t * @access private\n\t * @param {object} song \t- The song object of the song we are changing to.\n\t * @param {number} index \t- The index of the song in the songs object we are changing.\n\t */\n\tfunction setNewSong( song, index ){\n\t\tconfig.active_song.src \t= song.url;\n\t\tconfig.active_metadata \t= song;\n\t\tconfig.active_album \t= song.album;\n\t\tconfig.active_index \t\t= index;\n\t}\n\n\t/**\n\t * Shuffles individual songs in the config\n\t * Based off of: http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html\n\t *\n\t * Public Accessor: AmplitudeHelpers.shuffleSongs()\n\t *\n\t * @access public\n\t */\n\tfunction shuffleSongs(){\n\t\t/*\n\t\t\tBuilds a temporary array with the length of the config.\n\t\t*/\n\t\tlet shuffleTemp = new Array( config.songs.length );\n\n\t\t/*\n\t\t\tSet the temporary array equal to the songs array.\n\t\t*/\n\t\tfor( let i = 0; i < config.songs.length; i++ ){\n\t\t\tshuffleTemp[i] = config.songs[i];\n\t\t\tshuffleTemp[i].original_index = i;\n\t\t}\n\n\t\t/*\n\t\t\tIterate ove rthe songs and generate random numbers to\n\t\t\tswap the indexes of the shuffle array.\n\t\t*/\n\t\tfor( let i = config.songs.length - 1; i > 0; i-- ){\n\t\t\tlet randNum = Math.floor( ( Math.random() * config.songs.length ) + 1 );\n\t\t\tshuffleSwap( shuffleTemp, i, randNum - 1 );\n\t\t}\n\n\t\t/*\n\t\t\tSet the shuffle list to the shuffle temp.\n\t\t*/\n\t\tconfig.shuffle_list = shuffleTemp;\n\t}\n\n\t/**\n\t * Shuffle songs in a playlist\n\t *\n\t * Public Accessor: AmplitudeHelpers.shufflePlaylistSongs( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist - The playlist we are shuffling.\n\t */\n\tfunction shufflePlaylistSongs( playlist ){\n\t\t/*\n\t\t\tBuilds a temporary array with the length of the playlist songs.\n\t\t*/\n\t\tlet shuffleTemp = new Array( config.playlists[playlist].length );\n\n\t\t/*\n\t\t\tSet the temporary array equal to the playlist array.\n\t\t*/\n\t\tfor( let i = 0; i < config.playlists[playlist].length; i++ ){\n\t\t\tshuffleTemp[i] = config.songs[ config.playlists[playlist][i] ];\n\t\t\tshuffleTemp[i].original_index = config.playlists[playlist][i];\n\t\t}\n\n\t\t/*\n\t\t\tIterate ove rthe songs and generate random numbers to\n\t\t\tswap the indexes of the shuffle array.\n\t\t*/\n\t\tfor( let i = config.playlists[playlist].length - 1; i > 0; i-- ){\n\t\t\tlet randNum = Math.floor( ( Math.random() * config.playlists[playlist].length ) + 1 );\n\t\t\tshuffleSwap( shuffleTemp, i, randNum - 1 );\n\t\t}\n\n\t\t/*\n\t\t\tSet the shuffle list to the shuffle temp.\n\t\t*/\n\t\tconfig.shuffled_playlists[playlist] = shuffleTemp;\n\t}\n\n\t/**\n\t * Swaps and randomizes the song shuffle.\n\t *\n\t * @access private\n\t * @param {object} shuffleList \t- The list of songs that is going to be shuffled\n\t * @param {number} original \t\t- The original index of he song in the songs array\n\t * @param {number} random \t\t\t- The randomized index that will be the new index of the song in the shuffle array.\n\t */\n\tfunction shuffleSwap( shuffleList, original, random ){\n\t\tlet temp = shuffleList[ original ];\n\t\tshuffleList[ original ] = shuffleList[ random ];\n\t\tshuffleList[ random ] = temp;\n\t}\n\n\t/**\n\t * Sets the active playlist\n\t *\n\t * Public Accessor: AmplitudeHelpers.setActivePlaylist( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist - The string of the playlist being set to active.\n\t */\n\tfunction setActivePlaylist( playlist ){\n\t\t/*\n\t\t\tIf the active playlist is different than the playlist being set,\n\t\t\twe run the `playlist_changed` callback.\n\t\t*/\n\t\tif( config.active_playlist != playlist ){\n\t\t\trunCallback('playlist_changed');\n\t\t}\n\n\t\t/*\n\t\t\tSet the active playlist to the playlist parameter.\n\t\t*/\n\t\tconfig.active_playlist = playlist;\n\t}\n\n\t/**\n\t * Determines if the string passed in is a URL or not\n\t *\n\t * Public Accessor: AmplitudeHelpers.isURL( url )\n\t *\n\t * @access public\n\t * @param {string} url - The string we are testing to see if it's a URL.\n\t * @returns {boolean} True if the string is a url, false if it is not.\n\t */\n\tfunction isURL( url ){\n\t\t/*\n\t\t\tTest the string against the URL pattern and return if it matches\n\t\t*/\n\t\tlet pattern = /(ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?/\n\n\t\treturn pattern.test( url );\n\t}\n\n\t/**\n\t * Determines if what is passed in is an integer or not.\n\t *\n\t * Public Accessor: AmplitudeHelpers.isInt( int )\n\t *\n\t * @access public\n\t * @param {string|number} int - The variable we are testing to see is an integer or not.\n\t * @returns {boolean} If the variable is an integer or not.\n\t */\n\tfunction isInt( int ){\n\t\treturn !isNaN( int ) &&\n \t\tparseInt( Number( int ) ) == int &&\n \t\t!isNaN( parseInt( int, 10 ) );\n\t}\n\n\t/*\n\t\tReturns the public functions\n\t*/\n\treturn {\n\t\tresetConfig: resetConfig,\n\t\twriteDebugMessage: writeDebugMessage,\n\t\trunCallback: runCallback,\n\t\tchangeSong: changeSong,\n\t\tcheckNewSong: checkNewSong,\n\t\tcheckNewAlbum: checkNewAlbum,\n\t\tcheckNewPlaylist: checkNewPlaylist,\n\t\tshuffleSongs: shuffleSongs,\n\t\tshufflePlaylistSongs: shufflePlaylistSongs,\n\t\tsetActivePlaylist: setActivePlaylist,\n\t\tisURL: isURL,\n\t\tisInt: isInt\n\t}\n})();\n\nexport default AmplitudeHelpers\n\n\n\n// WEBPACK FOOTER //\n// ./src/core/helpers.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the Amplitude Visual Sync Helpers to keep the display in sync\n * @module visual/AmplitudeVisualSyncHelpers\n */\nimport AmplitudeVisualSyncHelpers from './helpers.js';\n\n\n/**\n * Helps with the syncing of the display data\n *\n * @module visual/AmplitudeVisualSync\n */\nlet AmplitudeVisualSync = (function() {\n\t/**\n\t * Visually displays the current time on the screen. This is called on\n\t * time update for the current song.\n\t *\n\t * @access public\n\t * @param {object} currentTime \t\t\t\t\t- An object containing the current time for the song in seconds, minutes, and hours.\n\t * @param {float} completionPercentage\t- The percent of the way through the song the user is at.\n\t */\n\tfunction syncCurrentTime( currentTime, completionPercentage ){\n\t\t/*\n\t\t\tSet current hour display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentHours( currentTime.hours );\n\n\t\t/*\n\t\t\tSet current minute display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentMinutes( currentTime.minutes );\n\n\t\t/*\n\t\t\tSet current second display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentSeconds( currentTime.seconds );\n\n\t\t/*\n\t\t\tSet current time display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCurrentTime( currentTime );\n\n\t\t/*\n\t\t\tSet all song sliders to be to the current percentage\n\t\t\tof the song played.\n\t\t*/\n\t\tsyncMainSliderLocation( completionPercentage );\n\t\tsyncPlaylistSliderLocation( config.active_playlist, completionPercentage );\n\t\tsyncSongSliderLocation( config.active_playlist, config.active_index, completionPercentage );\n\n\t\tAmplitudeVisualSyncHelpers.syncSongPlayedProgressBar( completionPercentage );\n\t}\n\n\t/**\n\t * Visually sync all of the times to the initial time of 0. This is so\n\t * we can keep all the players in sync\n\t *\n\t * @access public\n\t */\n\tfunction resetTimes(){\n\t\tAmplitudeVisualSyncHelpers.resetCurrentHours();\n\t\tAmplitudeVisualSyncHelpers.resetCurrentMinutes();\n\t\tAmplitudeVisualSyncHelpers.resetCurrentSeconds();\n\t\tAmplitudeVisualSyncHelpers.resetCurrentTime();\n\t}\n\n\t/**\n\t * Visually syncs the song sliders back to 0. This usually happens when\n\t * a song has changed, we ensure that all song sliders get reset.\n\t *\n\t * @access public\n\t */\n\tfunction resetSongSliders(){\n\t\tlet songSliders = document.getElementsByClassName(\"amplitude-song-slider\");\n\n\t\t/*\n\t\t\tIterate over all of the song sliders and set them to\n\t\t\t0 essentially resetting them.\n\t\t*/\n\t\tfor( let i = 0; i < songSliders.length; i++ ){\n\t\t\tsongSliders[i].value = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the song buffered progress bars to 0\n\t *\n\t * @access public\n\t */\n\tfunction resetSongBufferedProgressBars(){\n\t\t/*\n\t\t\tGets all of the song buffered progress bars.\n\t\t*/\n\t\tlet songBufferedProgressBars = document.getElementsByClassName(\"amplitude-buffered-progress\");\n\n\t\t/*\n\t\t\tIterate over all of the song buffered progress bar and\n\t\t\tset them to 0 which is like re-setting them.\n\t\t*/\n\t\tfor( let i = 0; i < songBufferedProgressBars.length; i++ ){\n\t\t\tsongBufferedProgressBars[i].value = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the song played progress bars to 0\n\t *\n\t * @access public\n\t */\n\tfunction resetSongPlayedProgressBars(){\n\t\tlet songPlayedProgressBars = document.getElementsByClassName(\"amplitude-song-played-progress\");\n\n\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\tsongPlayedProgressBars[i].value = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Applies the class 'amplitude-active-song-container' to the element\n\t * containing visual information regarding the active song.\n\t *\n\t * @access public\n\t */\n\tfunction setActiveContainer(){\n\t\tlet songContainers = document.getElementsByClassName('amplitude-song-container');\n\n\t\t/*\n\t\t\tRemoves all of the active song containrs.\n\t\t*/\n\t\tfor( let i = 0; i < songContainers.length; i++ ){\n\t\t\tsongContainers[i].classList.remove('amplitude-active-song-container');\n\t\t}\n\n\t\t/*\n\t\t\tFinds the active index and adds the active song container to the element\n\t\t\tthat represents the song at the index.\n\t\t*/\n\t\tif( config.active_playlist == '' || config.active_playlist == null ){\n\t\t\tif( document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"]') ){\n\t\t\t\tlet songContainers = document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songContainers.length; i++ ){\n\t\t\t\t\tif( !songContainers[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tsongContainers[i].classList.add('amplitude-active-song-container');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\tif( document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"][amplitude-playlist=\"'+config.active_playlist+'\"]') ){\n\t\t\t\tlet songContainers = document.querySelectorAll('.amplitude-song-container[amplitude-song-index=\"'+config.active_index+'\"][amplitude-playlist=\"'+config.active_playlist+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songContainers.length; i++ ){\n\t\t\t\t\tsongContainers[i].classList.add('amplitude-active-song-container');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Displays the active song's metadata. This is called after a song has\n\t * been changed. This method takes the active song and displays the\n\t * metadata. So once the new active song is set, we update all of the\n\t * screen elements.\n\t *\n\t * @access public\n\t */\n\tfunction displaySongMetadata(){\n\t\t/*\n\t\t\tDefine the image meta data keys. These are managed separately\n\t\t\tsince we aren't actually changing the inner HTML of these elements.\n\t\t*/\n\t\tlet imageMetaDataKeys \t= ['cover_art_url', 'station_art_url', 'podcast_episode_cover_art_url'];\n\n\t\t/*\n\t\t\tThese are the ignored keys that we won't be worrying about displaying.\n\t\t\tEvery other key in the song object can be displayed.\n\t\t*/\n\t\tlet ignoredKeys \t\t= ['url', 'live'];\n\n\t\t/*\n\t\t\tGet all of the song info elements\n\t\t*/\n\t\tlet songInfoElements = document.querySelectorAll('[amplitude-song-info]');\n\n\t\t/*\n\t\t\tIterate over all of the song info elements. We will either\n\t\t\tset these to the new values, or clear them if the active song\n\t\t\tdoesn't have the info set.\n\t\t*/\n\t\tfor( let i = 0; i < songInfoElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tGet the info so we can check if the active meta data has the\n\t\t\t\tkey.\n\t\t\t*/\n\t\t\tlet info = songInfoElements[i].getAttribute('amplitude-song-info');\n\n\t\t\t/*\n\t\t\t\tGet the song info element playlist.\n\t\t\t*/\n\t\t\tlet playlist = songInfoElements[i].getAttribute('amplitude-playlist');\n\n\t\t\t/*\n\t\t\t\tGet the main song info flag.\n\t\t\t*/\n\t\t\tlet main = songInfoElements[i].getAttribute('amplitude-main-song-info');\n\n\t\t\t/*\n\t\t\t\tIf the playlists match or the element is a main element, then\n\t\t\t\twe set the song info.\n\t\t\t*/\n\t\t\tif( config.active_playlist == playlist || main == 'true' ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active metadata has the key, then we set it,\n\t\t\t\t\totherwise we clear it. If it's an image element then\n\t\t\t\t\twe default it to the default info if needed.\n\t\t\t\t*/\n\t\t\t\tif( config.active_metadata[info] != undefined ){\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', config.active_metadata[info]);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = config.active_metadata[info];\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tWe look for the default album art because\n\t\t\t\t\t\tthe actual key didn't exist. If the default album\n\t\t\t\t\t\tart doesn't exist then we set the src attribute\n\t\t\t\t\t\tto null.\n\t\t\t\t\t*/\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tif( config.default_album_art != '' ){\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', config.default_album_art);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', '');\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = '';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n * Sets the first song in the playlist. This is used to fill in the meta\n\t * data in the playlist\n\t *\n\t * @param {object} song \t\t\t- The song we are setting to be the first song in the playlist\n\t * @param {string} playlist \t- Key of the playlist we are setting the first song in\n\t */\n\tfunction setFirstSongInPlaylist( song, playlist ){\n\t\t/*\n\t\t\tDefine the image meta data keys. These are managed separately\n\t\t\tsince we aren't actually changing the inner HTML of these elements.\n\t\t*/\n\t\tlet imageMetaDataKeys \t= ['cover_art_url', 'station_art_url', 'podcast_episode_cover_art_url'];\n\n\t\t/*\n\t\t\tThese are the ignored keys that we won't be worrying about displaying.\n\t\t\tEvery other key in the song object can be displayed.\n\t\t*/\n\t\tlet ignoredKeys \t\t= ['url', 'live'];\n\n\t\t/*\n\t\t\tGet all of the song info elements\n\t\t*/\n\t\tlet songInfoElements = document.querySelectorAll('[amplitude-song-info][amplitude-playlist=\"'+playlist+'\"]');\n\n\t\t/*\n\t\t\tIterate over all of the song info elements. We will either\n\t\t\tset these to the new values, or clear them if the active song\n\t\t\tdoesn't have the info set.\n\t\t*/\n\t\tfor( let i = 0; i < songInfoElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tGet the info so we can check if the active meta data has the\n\t\t\t\tkey.\n\t\t\t*/\n\t\t\tlet info = songInfoElements[i].getAttribute('amplitude-song-info');\n\n\t\t\t/*\n\t\t\t\tGet the song info element playlist.\n\t\t\t*/\n\t\t \tlet elementPlaylist = songInfoElements[i].getAttribute('amplitude-playlist');\n\n\t\t\t/*\n\t\t\t\tIf the playlists match or the element is a main element, then\n\t\t\t\twe set the song info.\n\t\t\t*/\n\t\t\tif( elementPlaylist == playlist ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active metadata has the key, then we set it,\n\t\t\t\t\totherwise we clear it. If it's an image element then\n\t\t\t\t\twe default it to the default info if needed.\n\t\t\t\t*/\n\t\t\t\tif( song[info] != undefined ){\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', song[info]);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = song[info];\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tWe look for the default album art because\n\t\t\t\t\t\tthe actual key didn't exist. If the default album\n\t\t\t\t\t\tart doesn't exist then we set the src attribute\n\t\t\t\t\t\tto null.\n\t\t\t\t\t*/\n\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\tif( song.default_album_art != '' ){\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', song.default_album_art);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', '');\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsongInfoElements[i].innerHTML = '';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the visual playback speed buttons to have the right class\n\t * to display the background image that represents the current playback\n\t * speed.\n\t *\n\t * @access public\n\t */\n\tfunction syncPlaybackSpeed(){\n\t\t/*\n\t\t\tGets all of the playback speed classes.\n\t\t*/\n\t\tlet playbackSpeedClasses = document.getElementsByClassName(\"amplitude-playback-speed\");\n\n\t\t/*\n\t\t\tIterates over all of the playback speed classes\n\t\t\tapplying the right speed class for visual purposes.\n\t\t*/\n\t\tfor( let i = 0; i < playbackSpeedClasses.length; i++ ){\n\t\t\t/*\n\t\t\t\tRemoves all of the old playback speed classes.\n\t\t\t*/\n\t\t\tplaybackSpeedClasses[i].classList.remove('amplitude-playback-speed-10');\n\t\t\tplaybackSpeedClasses[i].classList.remove('amplitude-playback-speed-15');\n\t\t\tplaybackSpeedClasses[i].classList.remove('amplitude-playback-speed-20');\n\n\t\t\t/*\n\t\t\t\tSwitch the current playback speed and apply the appropriate\n\t\t\t\tspeed class.\n\t\t\t*/\n\t\t\tswitch( config.playback_speed ){\n\t\t\t\tcase 1:\n\t\t\t\t\tplaybackSpeedClasses[i].classList.add('amplitude-playback-speed-10');\n\t\t\t\tbreak;\n\t\t\t\tcase 1.5:\n\t\t\t\t\tplaybackSpeedClasses[i].classList.add('amplitude-playback-speed-15');\n\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tplaybackSpeedClasses[i].classList.add('amplitude-playback-speed-20');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the buffered progress bars to the current percentage in the config\n\t *\n\t * @access public\n\t */\n\tfunction syncBufferedProgressBars(){\n\t\t/*\n\t\t\tGets all of the song buffered progress bars.\n\t\t*/\n\t\tlet songBufferedProgressBars = document.getElementsByClassName(\"amplitude-buffered-progress\");\n\n\t\t/*\n\t\t\tIterate over all of the song buffered progress bar and\n\t\t\tset them to 0 which is like re-setting them.\n\t\t*/\n\t\tfor( let i = 0; i < songBufferedProgressBars.length; i++ ){\n\t\t\tsongBufferedProgressBars[i].value = parseFloat( parseFloat( config.buffered ) / 100 );\n\t\t}\n\t}\n\n\t/**\n\t * Visually syncs the volume sliders so they are all the same if there\n\t * are more than one.\n\t *\n\t * @access public\n\t */\n\tfunction syncVolumeSliders(){\n\t\tlet amplitudeVolumeSliders = document.getElementsByClassName(\"amplitude-volume-slider\");\n\n\t\t/*\n\t\t\tIterates over all of the volume sliders for the song, setting the value\n\t\t\tto the config value.\n\t\t*/\n\t\tfor( let i = 0; i < amplitudeVolumeSliders.length; i++ ){\n\t\t\tamplitudeVolumeSliders[i].value = config.active_song.volume * 100;\n\t\t}\n\t}\n\n\t/**\n\t * Sets all of the play pause buttons to paused.\n\t *\n\t * @access public\n\t */\n\tfunction setPlayPauseButtonsToPause(){\n\t\t/*\n\t\t\tGets all of the play pause elements\n\t\t*/\n\t\tlet playPauseElements = document.querySelectorAll('.amplitude-play-pause');\n\n\t\t/*\n\t\t\tSets all of the elements to pause\n\t\t*/\n\t\tfor( let i = 0; i < playPauseElements.length; i++ ){\n\t\t\tAmplitudeVisualSyncHelpers.setElementPause( playPauseElements[i] );\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the main play pause buttons to the state of the active song.\n\t *\n\t * @param {string} state The state of the player\n\t * @access public\n\t */\n\tfunction syncMainPlayPause( state ){\n\t\t/*\n\t\t\tEnsures we have a string for the state otherwise we grab the\n\t\t\tstate from the config.\n\t\t*/\n if( typeof state != \"string\" ){\n state = config.active_song.paused ? \"paused\" : \"playing\";\n\t\t}\n\n\t\t/*\n\t\t\tGet all play pause buttons.\n\t\t*/\n\t\tconst playPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-main-play-pause=\"true\"]');\n\n\t\t/*\n\t\t\tIterate over all of the play pause elements syncing the\n\t\t\tdisplay visually.\n\t\t*/\n\t\tfor( let i = 0; i < playPauseElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tDetermines what classes we should add and remove\n\t\t\t\tfrom the elements.\n\t\t\t*/\n\t\t\tswitch( state ){\n\t\t\t\tcase 'playing':\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( playPauseElements[i] );\n\t\t\t\tbreak;\n\t\t\t\tcase 'paused':\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( playPauseElements[i] );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the main playlist play pause buttons to the state of the active song.\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the play pause state for.\n\t * @param {string} state \t\t\t- Either playing or paused for the state of the active song.\n\t */\n\tfunction syncPlaylistPlayPause( playlist, state ){\n\t\t/*\n\t\t\tEnsures we have a string for the state otherwise we grab the\n\t\t\tstate from the config.\n\t\t*/\n if( typeof state != \"string\" ){\n state = config.active_song.paused ? \"paused\" : \"playing\";\n\t\t}\n\n\t\t/*\n\t\t\tGet all of the main playlist play pause elements\n\t\t*/\n\t\tlet playlistPlayPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-playlist-main-play-pause=\"true\"]');\n\n\t\t/*\n\t\t\tIterate over the play pause elements, syncing the state accordingly.\n\t\t*/\n\t\tfor( let i = 0; i < playlistPlayPauseElements.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the element has the same playlist attribute as the playlist\n\t\t\t\tpassed in and the state is playing, we set the element to\n\t\t\t\tbe playing otherwise we set it to pause. Setting to pause\n\t\t\t\tmeans the element doesn't match the active playlist or the\n\t\t\t\tstate is paused.\n\t\t\t*/\n\t\t\tif( playlistPlayPauseElements[i].getAttribute('amplitude-playlist') == playlist\n\t\t\t\t&& state == 'playing' ){\n\n\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( playlistPlayPauseElements[i] );\n\t\t\t}else{\n\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( playlistPlayPauseElements[i] );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the song play pause buttons to the state of the active song.\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the play pause state for.\n\t * @param {int} song \t\t\t\t\t- The index of the song we are syncing the state for\n\t * @param {string} state \t\t\t- Either playing or paused for the state of the active song.\n\t */\n\tfunction syncSongPlayPause( playlist, song, state ){\n\t\t/*\n\t\t\tEnsures we have a string for the state otherwise we grab the\n\t\t\tstate from the config.\n\t\t*/\n if( typeof state != \"string\" ){\n state = config.active_song.paused ? \"paused\" : \"playing\";\n\t\t}\n\n\t\t/*\n\t\t\tIf the playlist is null or empty, we make sure that any song\n\t\t\tthat is a part of a playlist is set to paused.\n\t\t*/\n\t\tif( playlist == null || playlist == '' ){\n\t\t\t/*\n\t\t\t\tGet all of the individual song play pause buttons. These have an\n\t\t\t\tamplitude-song-index attribute. Some have amplitude-playlist which\n\t\t\t\tmeans they are individual songs within a playlist.\n\t\t\t*/\n\t\t\tlet songPlayPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-song-index]');\n\n\t\t\t/*\n\t\t\t\tIterate over all of the song play pause elements\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songPlayPauseElements.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tIf the song element has an attribute for amplitude-playlist then\n\t\t\t\t\twe set it to paused no matter what because the state of the player\n\t\t\t\t\tis not in a playlist mode.\n\t\t\t\t*/\n\t\t\t\tif( songPlayPauseElements[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the state of the song is playing and the song index matches the\n\t\t\t\t\t\tindex of the song we have, we set the element to playing otherwise\n\t\t\t\t\t\twe set the element to paused.\n\t\t\t\t\t*/\n\t\t\t\t\tif( state == 'playing' && songPlayPauseElements[i].getAttribute('amplitude-song-index') == song ){\n\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( songPlayPauseElements[i] );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tGet all of the individual song play pause buttons. These have an\n\t\t\t\tamplitude-song-index attribute. Some have amplitude-playlist which\n\t\t\t\tmeans they are individual songs within a playlist.\n\t\t\t*/\n\t\t\tlet songPlayPauseElements = document.querySelectorAll('.amplitude-play-pause[amplitude-song-index]');\n\n\t\t\t/*\n\t\t\t\tIterate over all of the individual play pause elements.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songPlayPauseElements.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tSince we have an active playlist this time, we want any stand alone\n\t\t\t\t\tsongs to be set to paused since the scope is within a playlist.\n\n\t\t\t\t\tWe check to see if the element has an amplitude-playlist attribute.\n\t\t\t\t*/\n\t\t\t\tif( songPlayPauseElements[i].hasAttribute('amplitude-playlist') ){\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the song index matches the index passed in and the\n\t\t\t\t\t\tplaylist matches the scoped playlist we are looking for and the\n\t\t\t\t\t\tstate of the player is playing, then we set the element to play. If those\n\t\t\t\t\t\tthree parameters are not met, set the element to pause.\n\t\t\t\t\t*/\n\t\t\t\t\tif( songPlayPauseElements[i].getAttribute('amplitude-song-index') == song\n\t\t\t\t\t\t&& songPlayPauseElements[i].getAttribute('amplitude-playlist') == playlist\n\t\t\t\t\t\t&& state == 'playing' ){\n\t\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPlay( songPlayPauseElements[i] );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet any individual songs (songs outside of a playlist scope) to pause\n\t\t\t\t\t\tsince we are in the scope of a playlist.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSyncHelpers.setElementPause( songPlayPauseElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs repeat for all of the repeat buttons. Users\n\t * can apply styles to the 'amplitude-repeat-on' and\n\t * 'amplitude-repeat-off' classes. They represent the state\n\t * of the player.\n\t */\n\tfunction syncRepeat(){\n\t\t/*\n\t\t\tGets all of the repeat classes\n\t\t*/\n\t\tlet repeatClasses = document.getElementsByClassName(\"amplitude-repeat\");\n\n\t\t/*\n\t\t\tIterate over all of the repeat classes. If repeat is on,\n\t\t\tthen add the 'amplitude-repeat-on' class and remove the\n\t\t\t'amplitude-repeat-off' class. If it's off, then do the\n\t\t\topposite.\n\t\t*/\n\t\tfor( let i = 0; i < repeatClasses.length; i++ ){\n\t\t\tif( config.repeat ){\n\t\t\t\trepeatClasses[i].classList.add('amplitude-repeat-on');\n\t\t\t\trepeatClasses[i].classList.remove('amplitude-repeat-off');\n\t\t\t}else{\n\t\t\t\trepeatClasses[i].classList.remove('amplitude-repeat-on');\n\t\t\t\trepeatClasses[i].classList.add('amplitude-repeat-off');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs repeat for all of the playlist repeat buttons. Users\n\t * can apply styles to the `amplitude-repeat-on` and `amplitude-repeat-off`\n\t * classes. They repreent the state of the playlist in the player.\n\t */\n\t function syncRepeatPlaylist( playlist ){\n\t\t /*\n\t\t\t Gets all of the repeat buttons.\n\t\t */\n\t\t let repeatButtons = document.getElementsByClassName(\"amplitude-repeat\");\n\n\t\t /*\n\t\t\t Iterate over all of the repeat buttons\n\t\t */\n\t\t for( let i = 0; i < repeatButtons.length; i++ ){\n\t\t\t /*\n\t\t\t\t Ensure that the repeat button belongs to matches the\n\t\t\t\t playlist we are syncing the state for.\n\t\t\t */\n\t\t\t if( repeatButtons[i].getAttribute('amplitude-playlist') == playlist ){\n\t\t\t\t /*\n\t\t\t\t\t If the state of the playlist is shuffled on, true, then\n\t\t\t\t\t we add the 'amplitude-repeat-on' class and remove the\n\t\t\t\t\t 'amplitude-repeat-off' class. If the player is not shuffled\n\t\t\t\t\t then we do the opposite.\n\t\t\t\t */\n\t\t\t\t if( config.repeat_statuses[playlist] ){\n\t\t\t\t\t repeatButtons[i].classList.add( 'amplitude-repeat-on');\n\t\t\t\t\t repeatButtons[i].classList.remove( 'amplitude-repeat-off');\n\t\t\t\t }else{\n\t\t\t\t\t repeatButtons[i].classList.add( 'amplitude-repeat-off');\n\t\t\t\t\t repeatButtons[i].classList.remove( 'amplitude-repeat-on');\n\t\t\t\t }\n\t\t\t }\n\t\t }\n\t }\n\n\t/**\n\t * Syncs repeat for all of the repeat song buttons. Users\n\t * can apply styles to the 'amplitude-repeat-song-on' and\n\t * 'amplitude-repeat-song-off' classes. They represent the state\n\t * of the player.\n\t */\n\tfunction syncRepeatSong(){\n\t\t/*\n\t\t\tGets all of the repeat song classes\n\t\t*/\n\t\tlet repeatSongClasses = document.getElementsByClassName(\"amplitude-repeat-song\");\n\n\t\t/*\n\t\t\tIterate over all of the repeat song classes. If repeat is on,\n\t\t\tthen add the 'amplitude-repeat-song-on' class and remove the\n\t\t\t'amplitude-repeat-song-off' class. If it's off, then do the\n\t\t\topposite.\n\t\t*/\n\t\tfor( let i = 0; i < repeatSongClasses.length; i++ ){\n\t\t\tif( config.repeat_song ){\n\t\t\t\trepeatSongClasses[i].classList.add('amplitude-repeat-song-on');\n\t\t\t\trepeatSongClasses[i].classList.remove('amplitude-repeat-song-off');\n\t\t\t}else{\n\t\t\t\trepeatSongClasses[i].classList.remove('amplitude-repeat-song-on');\n\t\t\t\trepeatSongClasses[i].classList.add('amplitude-repeat-song-off');\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs mute for all of the mute buttons. This represents the\n\t * state of the player if it's muted or not.\n\t *\n\t * @access public\n\t * @param {string} state \t- The muted state of the player.\n\t */\n\tfunction syncMute( state ){\n\t\t/*\n\t\t\tGet all of the mute buttons.\n\t\t*/\n\t\tlet muteClasses = document.getElementsByClassName(\"amplitude-mute\");\n\n\t\t/*\n\t\t\tIterate over all of the mute classes. If the state of the player\n\t\t\tis not-muted then we add the amplitude-not-muted classe and remove\n\t\t\tthe amplitude muted class otherwise we do the opposite.\n\t\t*/\n\t\tfor( let i = 0; i < muteClasses.length; i++ ){\n\t\t\tif( !state ){\n\t\t\t\tmuteClasses[i].classList.add( 'amplitude-not-muted' );\n\t\t\t\tmuteClasses[i].classList.remove( 'amplitude-muted' );\n\t\t\t}else{\n\t\t\t\tmuteClasses[i].classList.remove( 'amplitude-not-muted' );\n\t\t\t\tmuteClasses[i].classList.add( 'amplitude-muted' );\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the global shuffle button visual state.\n\t *\n\t * @access public\n\t * @param {boolean} state \t- The shuffled state of the player.\n\t */\n\tfunction syncShuffle( state ){\n\t\t/*\n\t\t\tGets the shuffle buttons.\n\t\t*/\n\t\tlet shuffleButtons = document.getElementsByClassName(\"amplitude-shuffle\");\n\n\t\t/*\n\t\t\tIterate over all of the shuffle buttons.\n\t\t*/\n\t\tfor( let i = 0; i < shuffleButtons.length; i++ ){\n\t\t\t/*\n\t\t\t\tEnsure the shuffle button doesn't belong to a playlist. We have\n\t\t\t\ta separate method for that.\n\t\t\t*/\n\t\t\tif( shuffleButtons[i].getAttribute('amplitude-playlist') == null ){\n\t\t\t\t/*\n\t\t\t\t\tIf the state of the player is shuffled on, true, then\n\t\t\t\t\twe add the 'amplitude-shuffle-on' class and remove the\n\t\t\t\t\t'amplitude-shuffle-off' class. If the player is not shuffled\n\t\t\t\t\tthen we do the opposite.\n\t\t\t\t*/\n\t\t\t\tif( state ){\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-on');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-off');\n\t\t\t\t}else{\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-off');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-on');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the playlist shuffle button visual state.\n\t *\n\t * @access public\n\t * @param {boolean} state \t- The shuffled state of the player.\n\t * @param {string} playlist - The playlist string the shuffle button belongs to.\n\t */\n\tfunction syncPlaylistShuffle( state, playlist ){\n\t\t/*\n\t\t\tGets all of the shuffle buttons.\n\t\t*/\n\t\tlet shuffleButtons = document.getElementsByClassName(\"amplitude-shuffle\");\n\n\t\t/*\n\t\t\tIterate over all of the shuffle buttons\n\t\t*/\n\t\tfor( let i = 0; i < shuffleButtons.length; i++ ){\n\t\t\t/*\n\t\t\t\tEnsure that the playlist the shuffle button belongs to matches the\n\t\t\t\tplaylist we are syncing the state for.\n\t\t\t*/\n\t\t\tif( shuffleButtons[i].getAttribute('amplitude-playlist') == playlist ){\n\t\t\t\t/*\n\t\t\t\t\tIf the state of the playlist is shuffled on, true, then\n\t\t\t\t\twe add the 'amplitude-shuffle-on' class and remove the\n\t\t\t\t\t'amplitude-shuffle-off' class. If the player is not shuffled\n\t\t\t\t\tthen we do the opposite.\n\t\t\t\t*/\n\t\t\t\tif( state ){\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-on');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-off');\n\t\t\t\t}else{\n\t\t\t\t\tshuffleButtons[i].classList.add( 'amplitude-shuffle-off');\n\t\t\t\t\tshuffleButtons[i].classList.remove( 'amplitude-shuffle-on');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the main slider location\n\t *\n\t * @access public\n\t * @param {number} location \t- The location of the song as a percentage.\n\t */\n\tfunction syncMainSliderLocation( location ){\n\t\t/*\n\t\t\tEnsure we have a location that's a number\n\t\t*/\n\t\tlocation = !isNaN( location ) ? location : 0;\n\n\t\t/*\n\t\t\tGets the main song sliders\n\t\t*/\n\t\tlet mainSongSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-main-song-slider=\"true\"]');\n\n\t\t/*\n\t\t\tIterates over all of the main sliders and sets the value to the\n\t\t\tpercentage of the song played.\n\t\t*/\n\t\tfor( let i = 0; i < mainSongSliders.length; i++ ){\n\t\t\tmainSongSliders[i].value = location;\n\t\t}\n\t}\n\n\t/**\n\t * Syncs playlist song slider locations\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the song slider for.\n\t * @param {number} location \t- The location of the song as a percentage.\n\t */\n\tfunction syncPlaylistSliderLocation( playlist, location ){\n\t\t/*\n\t\t\tEnsure we have a location that's a number\n\t\t*/\n\t\tlocation = !isNaN( location ) ? location : 0;\n\n\t\t/*\n\t\t\tGets the playlist song sliders\n\t\t*/\n\t\tlet playlistSongSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-playlist-song-slider=\"true\"][amplitude-playlist=\"'+playlist+'\"]');\n\n\t\t/*\n\t\t\tIterates over all of the playlist sliders and sets the value to the\n\t\t\tpercentage of the song played.\n\t\t*/\n\t\tfor( let i = 0; i < playlistSongSliders.length; i++ ){\n\t\t\tplaylistSongSliders[i].value = location;\n\t\t}\n\t}\n\n\t/**\n\t * Syncs individual song slider locations\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the song slider for.\n\t * @param {number} songIndex \t- The index of the song we are adjusting the song slider for.\n\t * @param {number} location \t- The location of the song as a percentage.\n\t */\n\tfunction syncSongSliderLocation( playlist, songIndex, location ){\n\t\t/*\n\t\t\tEnsure we have a location that's a number\n\t\t*/\n\t\tlocation = !isNaN( location ) ? location : 0;\n\t\t/*\n\t\t\tIf the playlist is set, we get all of the individual song sliders\n\t\t\tthat relate to the song and the playlist.\n\t\t*/\n\t\tif( playlist != '' && playlist != null ){\n\t\t\t/*\n\t\t\t\tGets the song sliders for the individual songs and the\n\t\t\t\tplaylist\n\t\t\t*/\n\t\t\tlet songSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-playlist=\"'+playlist+'\"][amplitude-song-index=\"'+songIndex+'\"]');\n\n\t\t\t/*\n\t\t\t\tIterates over all of the playlist sliders and set the value to the\n\t\t\t\tpercentage of the song played.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songSliders.length; i++ ){\n\t\t\t\tsongSliders[i].value = location;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tGet the individual song slider by index\n\t\t\t*/\n\t\t\tlet songSliders = document.querySelectorAll('.amplitude-song-slider[amplitude-song-index=\"'+songIndex+'\"]');\n\n\t\t\t/*\n\t\t\t\tIterats over all of the song sliders that have the index of\n\t\t\t\tthe song we are sliding. If the song doesn't have a playlist\n\t\t\t\tattribute, we set the location.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < songSliders.length; i++ ){\n\t\t\t\tif( !songSliders[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\tif( location != 0 ){\n\t\t\t\t\t\tsongSliders[i].value = location;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets the volume slider location\n\t *\n\t * @access public\n\t * @param {number} volume \t- The volume from 0 - 1 for song volume.\n\t */\n\tfunction syncVolumeSliderLocation( volume ){\n\t\t/*\n\t\t\tGets all of the volume sliders\n\t\t*/\n\t\tlet volumeSliders = document.querySelectorAll('.amplitude-volume-slider');\n\n\t\t/*\n\t\t\tIterates over all of the sliders and sets their volume\n\t\t\tto the volume of the song.\n\t\t*/\n\t\tfor( let i = 0; i < volumeSliders.length; i++ ){\n\t\t\tvolumeSliders[i].value = volume;\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the song's duration\n\t *\n\t * @access public\n\t * @param {object} currentTime \t\t- Object containing information about the current time of the song.\n\t * @param {object} songDuration \t- Object containing information about the duration of the song.\n\t */\n\tfunction syncSongDuration( currentTime, songDuration ){\n\t\t/*\n\t\t\tSet duration hour display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationHours( songDuration != undefined && !isNaN( songDuration.hours ) ? songDuration.hours : '00' );\n\n\t\t/*\n\t\t\tSet duration minute display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationMinutes( songDuration != undefined && !isNaN( songDuration.minutes ) ? songDuration.minutes : '00' );\n\n\t\t/*\n\t\t\tSet duration second display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationSeconds( songDuration != undefined && !isNaN( songDuration.seconds ) ? songDuration.seconds : '00' );\n\n\t\t/*\n\t\t\tSet duration time display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncDurationTime( songDuration != undefined ? songDuration : {} );\n\n\t\t/*\n\t\t\tSet count down time display.\n\t\t*/\n\t\tAmplitudeVisualSyncHelpers.syncCountDownTime( currentTime, songDuration );\n\t}\n\n\t/**\n\t * Sets the meta data for songs loaded in the songs array\n\t */\n\t function syncSongsMetaData(){\n\t\t /*\n \t\t\tDefine the image meta data keys. These are managed separately\n \t\t\tsince we aren't actually changing the inner HTML of these elements.\n \t\t*/\n \t\tlet imageMetaDataKeys \t= ['cover_art_url', 'station_art_url', 'podcast_episode_cover_art_url'];\n\n \t\t/*\n \t\t\tThese are the ignored keys that we won't be worrying about displaying.\n \t\t\tEvery other key in the song object can be displayed.\n \t\t*/\n \t\tlet ignoredKeys \t\t= ['url', 'live'];\n\n \t\t/*\n \t\t\tGet all of the song info elements\n \t\t*/\n \t\tlet songInfoElements = document.querySelectorAll('[amplitude-song-info]');\n\n \t\t/*\n \t\t\tIterate over all of the song info elements. We will either\n \t\t\tset these to the new values, or clear them if the active song\n \t\t\tdoesn't have the info set.\n \t\t*/\n \t\tfor( let i = 0; i < songInfoElements.length; i++ ){\n\n\t\t\t/*\n\t\t\t\tFor this method we do not want the element to have any playlist or\n\t\t\t\tmain song info. This way we aren't adjusting the main song information for the\n\t\t\t\tglobal player or the playlist player.\n\t\t\t*/\n\t\t\tif( songInfoElements[i].getAttribute('amplitude-playlist') == null\n\t\t\t\t\t&& songInfoElements[i].getAttribute('amplitude-main-song-info') == null\n\t\t\t\t && songInfoElements[i].getAttribute('amplitude-song-index') != null ){\n\n\t\t\t\t\t/*\n\t\t \t\t\t\tGet the info so we can check if the active meta data has the\n\t\t \t\t\t\tkey.\n\t\t \t\t\t*/\n\t\t \t\t\tlet info = songInfoElements[i].getAttribute('amplitude-song-info');\n\t\t\t\t\tlet index = songInfoElements[i].getAttribute('amplitude-song-index');\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tMake sure that the song index they are referencing is defined.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.songs[index][info] != undefined ){\n\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tIf it's an image meta data key, then we set the src attribute of\n\t\t\t\t\t\t\tthe element. Otherwise we set the inner HTML of the element.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif( imageMetaDataKeys.indexOf( info ) >= 0 ){\n\t\t\t\t\t\t\tsongInfoElements[i].setAttribute('src', config.songs[index][info]);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tsongInfoElements[i].innerHTML = config.songs[index][info];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t \t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t\tReturns the publically available functions\n\t\t@TODO Re-order to order of methods in module\n\t*/\n\treturn {\n\t\tsyncCurrentTime: syncCurrentTime,\n\t\tresetTimes: resetTimes,\n\t\tresetSongSliders: resetSongSliders,\n\t\tresetSongPlayedProgressBars: resetSongPlayedProgressBars,\n\t\tresetSongBufferedProgressBars: resetSongBufferedProgressBars,\n\t\tsetActiveContainer: setActiveContainer,\n\t\tdisplaySongMetadata: displaySongMetadata,\n\t\tsyncPlaybackSpeed: syncPlaybackSpeed,\n\t\tsyncBufferedProgressBars: syncBufferedProgressBars,\n\t\tsyncVolumeSliders: syncVolumeSliders,\n\t\tsetPlayPauseButtonsToPause: setPlayPauseButtonsToPause,\n\t\tsetFirstSongInPlaylist: setFirstSongInPlaylist,\n\t\tsyncMainPlayPause: syncMainPlayPause,\n\t\tsyncPlaylistPlayPause: syncPlaylistPlayPause,\n\t\tsyncSongPlayPause: syncSongPlayPause,\n\t\tsyncRepeat: syncRepeat,\n\t\tsyncRepeatSong: syncRepeatSong,\n\t\tsyncRepeatPlaylist: syncRepeatPlaylist,\n\t\tsyncMute: syncMute,\n\t\tsyncShuffle: syncShuffle,\n\t\tsyncPlaylistShuffle: syncPlaylistShuffle,\n\t\tsyncMainSliderLocation: syncMainSliderLocation,\n\t\tsyncPlaylistSliderLocation: syncPlaylistSliderLocation,\n\t\tsyncSongSliderLocation: syncSongSliderLocation,\n\t\tsyncVolumeSliderLocation: syncVolumeSliderLocation,\n\t\tsyncSongDuration: syncSongDuration,\n\t\tsyncSongsMetaData: syncSongsMetaData\n\t}\n})();\n\nexport default AmplitudeVisualSync\n\n\n\n// WEBPACK FOOTER //\n// ./src/visual/visual.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * AmplitudeJS Core Helpers\n * @module core/helpers\n */\nimport AmplitudeHelpers from './helpers.js';\n\n/**\n * AmplitudeJS Visual Sync\n * @module visual/visual\n*/\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * Interacts directly with native functions of the Audio element. Logic\n * leading up to these methods are handled by click handlers which call\n * helpers and visual synchronizers. These are the core functions of AmplitudeJS.\n * Every other function that leads to these prepare the information to be\n * acted upon by these functions.\n *\n * @module core/AmplitudeCore\n */\nlet AmplitudeCore = (function() {\n\t/**\n\t * Plays the active song. If the current song is live, it reconnects\n\t * the stream before playing.\n\t *\n\t * Public Accessor: Amplitude.play()\n\t *\n\t * @access public\n\t */\n\tfunction play(){\n\t\t/*\n\t\t\tRun the before play callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('before_play');\n\n\t\t/*\n\t\t\tIf the audio is live we re-conenct the stream.\n\t\t*/\n\t\tif( config.active_metadata.live ){\n\t\t\treconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tMobile remote sources need to be reconnected on play. I think this is\n\t\t\tbecause mobile browsers are optimized not to load all resources\n\t\t\tfor speed reasons. We only do this if mobile and the paused button\n\t\t\tis not clicked. If the pause button was clicked then we don't reconnect\n\t\t\tor the user will lose their place in the stream.\n\t\t*/\n\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && !config.paused ) {\n\t\t\treconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tPlay the song and set the playback rate to the playback\n\t\t\tspeed.\n\t\t*/\n\t\tconfig.active_song.play();\n\t\tconfig.active_song.playbackRate = config.playback_speed;\n\n\t\t/*\n\t\t\tRun the after play callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_play');\n\t}\n\n\t/**\n\t * Pauses the active song. If it's live, it disconnects the stream.\n\t *\n\t * Public Accessor: Amplitude.pause()\n\t *\n\t * @access public\n\t */\n\tfunction pause(){\n\t\t/*\n\t\t\tRun the before pause callback.\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('before_pause');\n\n\t\t/*\n\t\t\tPause the active song.\n\t\t*/\n\t\tconfig.active_song.pause();\n\n\t\t/*\n\t\t\tFlag that pause button was clicked.\n\t\t*/\n\t\tconfig.paused = true;\n\n\t\t/*\n\t\t\tIf the song is live, we disconnect the stream so we aren't\n\t\t\tsaving it to memory.\n\t\t*/\n\t\tif( config.active_metadata.live ){\n\t\t\tdisconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tRun the after pause callback.\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_pause');\n\t}\n\n\t/**\n\t * Stops the active song by setting the current song time to 0.\n\t * When the user resumes, it will be from the beginning.\n\t * If it's a live stream it disconnects.\n\t *\n\t * Public Accessor: Amplitude.stop()\n\t *\n\t * @access public\n\t */\n\tfunction stop(){\n\t\t/*\n\t\t\tRuns the before stop callback.\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('before_stop');\n\n\t\t/*\n\t\t\tSet the current time of the song to 0 which will reset the song.\n\t\t*/\n\t\tif( config.active_song.currentTime != 0 ){\n\t\t\tconfig.active_song.currentTime = 0;\n\t\t}\n\n\t\t/*\n\t\t\tRun pause so the song will stop\n\t\t*/\n\t\tconfig.active_song.pause();\n\n\t\t/*\n\t\t\tIf the song is live, disconnect the stream.\n\t\t*/\n\t\tif( config.active_metadata.live ){\n\t\t\tdisconnectStream();\n\t\t}\n\n\t\t/*\n\t\t\tRun the after stop callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_stop');\n\t}\n\n\t/**\n\t * Sets the song volume.\n\t *\n\t * Public Accessor: Amplitude.setVolume( volumeLevel )\n\t *\n\t * @access public\n\t * @param {number} volumeLevel - A number between 1 and 100 as a percentage of\n\t * min to max for a volume level.\n\t */\n\tfunction setVolume( volumeLevel ){\n\t\t/*\n\t\t\tIf the volume is set to mute somewhere else, we sync the display.\n\t\t*/\n\t\tif( volumeLevel == 0 ){\n\t\t\tAmplitudeVisualSync.syncMute( true );\n\t\t}else{\n\t\t\tAmplitudeVisualSync.syncMute( false );\n\t\t}\n\n\t\t/*\n\t\t\tSet the volume of the active song.\n\t\t*/\n\t\tconfig.active_song.volume = volumeLevel / 100;\n\t}\n\n\t/**\n\t * Sets the song percentage. If it's a live song, we ignore this because\n\t * we can't skip ahead. This is an issue if you have a playlist with\n\t * a live source.\n\t *\n\t * Public Accessor: Amplitude.setSongLocation( songPercentage )\n\t *\n\t * @access public\n\t * @param {number} songPercentage - A number between 1 and 100 as a percentage of song completion.\n\t */\n\tfunction setSongLocation( songPercentage ){\n\t\t/*\n\t\t\tAs long as the song is not live, we can set the current time of the\n\t\t\tsong to the percentage the user passed in.\n\t\t*/\n\t\tif( !config.active_metadata.live ){\n\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( song_percentage / 100 );\n\t\t}\n\t}\n\n\t/**\n\t * Skips to a location in a song\n\t *\n\t * Public Accessor: Amplitude.skipToLocation( seconds )\n\t *\n\t * @access public\n\t * @param {number} seconds - An integer containing the seconds to skip to\n\t */\n\tfunction skipToLocation( seconds ){\n\t\t/*\n\t\t\tWhen the active song can be played through, we can check to\n\t\t\tsee if the seconds will work. We only bind the event handler\n\t\t\tonce and remove it once it's fired.\n\t\t*/\n\t\tconfig.active_song.addEventListener('canplaythrough', function(){\n\t\t\t/*\n\t\t\t\tIf the active song duration is greater than or equal to the\n\t\t\t\tamount of seconds the user wants to skip to and the seconds\n\t\t\t\tis greater than 0, we skip to the seconds defined.\n\t\t\t*/\n\t\t\tif( config.active_song.duration >= seconds && seconds > 0 ){\n\t\t\t\tconfig.active_song.currentTime = seconds;\n\t\t\t}else{\n\t\t\t\tAmplitudeHelpers.writeDebugMessage('Amplitude can\\'t skip to a location greater than the duration of the audio or less than 0');\n\t\t\t}\n\t\t}, { once: true });\n\t}\n\n\t/**\n\t * Disconnects the live stream\n\t *\n\t * Public Accessor: Amplitude.disconnectStream()\n\t *\n\t * @access public\n\t */\n\tfunction disconnectStream(){\n\t\tconfig.active_song.src = '';\n\t\tconfig.active_song.load();\n\t}\n\n\t/**\n\t * Reconnects the live stream\n\t *\n\t * Public Accessor: Amplitude.reconnectStream()\n\t *\n\t * @access public\\\n\t */\n\tfunction reconnectStream(){\n\t\tconfig.active_song.src = config.active_metadata.url;\n\t\tconfig.active_song.load();\n\t}\n\n\t/**\n\t * When you pass a song object it plays that song right awawy. It sets\n\t * the active song in the config to the song you pass in and synchronizes\n\t * the visuals.\n\t *\n\t * Public Accessor: Amplitude.playNow( song )\n\t *\n\t * @access public\n\t * @param {object} song - JSON representation of a song.\n\t */\n\tfunction playNow( song ){\n\t\t/*\n\t\t\tMakes sure the song object has a URL associated with it\n\t\t\tor there will be nothing to play.\n\t\t*/\n\t\tif( song.url ){\n\t\t\tconfig.active_song.src \t= song.url;\n\t\t\tconfig.active_metadata \t= song;\n\t\t\tconfig.active_album \t= song.album;\n\t\t}else{\n\t\t\t/*\n\t\t\t\tWrite error message since the song passed in doesn't\n\t\t\t\thave a URL.\n\t\t\t*/\n\t\t\tAmplitudeHelpers.writeDebugMessage('The song needs to have a URL!');\n\t\t}\n\n\t\t/*\n\t\t\tSets the main song control status visual\n\t\t*/\n\t\tAmplitudeVisualSync.syncMainPlayPause('playing');\n\n\t\t/*\n\t\t\tUpdate the song meta data\n\t\t*/\n\t\tAmplitudeVisualSync.displaySongMetadata();\n\n\n\t\t/*\n\t\t\tReset the song sliders, song progress bar info, and\n\t\t\treset times. This ensures everything stays in sync.\n\t\t*/\n\t\tAmplitudeVisualSync.resetSongSliders();\n\n\t\tAmplitudeVisualSync.resetSongPlayedProgressBars();\n\n\t\tAmplitudeVisualSync.resetTimes();\n\n\t\t/*\n\t\t\tPlays the song.\n\t\t*/\n\t\tplay();\n\t}\n\n\t/**\n\t * Plays the song at a specific index in the songs array\n\t *\n\t * Public Accessor: Amplitude.playSongAtIndex( song )\n\t *\n\t * @access public\n\t * @param {number} index - The number representing the song in the songs array\n\t */\n\t function playSongAtIndex( index ){\n\t\t /*\n\t\t\t\tStop the current song.\n\t\t */\n\t\t stop();\n\n\t\t /*\n\t\t\t\tDetermine if there is a new playlist, if so set the active playlist and change the song.\n\t\t */\n\t\t if( AmplitudeHelpers.checkNewPlaylist( null ) ){\n\t\t\t AmplitudeHelpers.setActivePlaylist( null );\n\n\t\t\t AmplitudeHelpers.changeSong( index );\n\t\t }\n\n\t\t /*\n\t\t\t\tCheck if the song is new. If so, change the song.\n\t\t */\n\t\t if( AmplitudeHelpers.checkNewSong( index ) ){\n\t\t\t AmplitudeHelpers.changeSong( index );\n\t\t }\n\n\t\t /*\n\t\t\t Sync all of the play pause buttons.\n\t\t */\n\t\t AmplitudeVisualSync.syncMainPlayPause('playing');\n\t\t AmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\t\t AmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t /*\n\t\t\t Play the song\n\t\t */\n\t\t play();\n\t }\n\n\t /**\n\t\t* Plays a song at the index passed in for the playlist provided. The index passed\n\t\t* in should be the index of the song in the playlist and not the songs array.\n\t\t*\n\t\t* @access public\n\t\t* @param {number} index \t\t- The number representing the song in the playlist array.\n\t\t* @param {string} playlist \t- The key string representing the playlist we are playing the song from.\n\t\t*\n\t\t*/\n\t function playPlaylistSongAtIndex( index, playlist ){\n\t\t\t /*\n\t\t\t \t\tStop the current song.\n\t\t\t */\n\t\t\t stop();\n\n\t\t\t /*\n\t\t\t \t\tGet the index of the song in the songs array. This is the integer at the index\n\t\t\t\t\tin the playlist.\n\t\t\t */\n\t\t\t let songIndex = config.playlists[ playlist ][ index ];\n\n\t\t\t /*\n\t\t\t \t\tDetermine if there is a new playlist, if so set the active playlist and change the song.\n\t\t\t */\n\t\t\t if( AmplitudeHelpers.checkNewPlaylist( playlist ) ){\n\t\t\t\t AmplitudeHelpers.setActivePlaylist( playlist );\n\n\t\t\t\t AmplitudeHelpers.changeSong( songIndex );\n\t\t\t }\n\n\t\t\t /*\n\t\t\t \t\tCheck if the song is new. If so, change the song.\n\t\t\t */\n\t\t\tif( AmplitudeHelpers.checkNewSong( songIndex ) ){\n\t\t\t AmplitudeHelpers.changeSong( songIndex );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSync all of the play pause buttons.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause('playing');\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tplay();\n\t }\n\n\t/**\n\t * Sets the playback speed for the song.\n\t *\n\t * @param {number} playbackSpeed The speed we want the song to play back at.\n\t */\n\tfunction setPlaybackSpeed( playbackSpeed ){\n\t\t/*\n\t\t\tSet the config playback speed.\n\t\t*/\n\t\tconfig.playback_speed = playbackSpeed;\n\n\t\t/*\n\t\t\tSet the active song playback rate.\n\t\t*/\n\t\tconfig.active_song.playbackRate = config.playback_speed;\n\t}\n\n\t/*\n\t\tReturn publically facing functions\n\t*/\n\treturn {\n\t\tplay: play,\n\t\tpause: pause,\n\t\tstop: stop,\n\t\tsetVolume: setVolume,\n\t\tsetSongLocation: setSongLocation,\n\t\tskipToLocation: skipToLocation,\n\t\tdisconnectStream: disconnectStream,\n\t\treconnectStream: reconnectStream,\n\t\tplayNow: playNow,\n\t\tplaySongAtIndex: playSongAtIndex,\n\t\tplayPlaylistSongAtIndex: playPlaylistSongAtIndex,\n\t\tsetPlaybackSpeed: setPlaybackSpeed\n\t}\n})();\n\nexport default AmplitudeCore\n\n\n\n// WEBPACK FOOTER //\n// ./src/core/core.js","/*\n\tImport the necessary classes and config to use\n\twith the events.\n*/\nimport config from '../config.js';\nimport AmplitudeHelpers from '../core/helpers.js';\nimport AmplitudeHandlers from './handlers.js';\n\n/*\n|----------------------------------------------------------------------------------------------------\n| EVENTS METHODS\n|----------------------------------------------------------------------------------------------------\n| These methods are called when we need to bind events to certain elements.\n|\n| METHODS:\n| \tinitializeEvents()\n|\tbindPlay()\n|\tbindPause()\n|\tbindPlayPause()\n|\tbindStop()\n|\tbindMute()\n|\tbindVolumeUp()\n|\tbindVolumeDown()\n|\tbindSongSlider()\n|\tbindVolumeSlider()\n|\tbindNext()\n|\tbindPrev()\n|\tbindShuffle()\n|\tbindRepeat()\n|\tbindPlaybackSpeed()\n|\tbindSkipTo()\n| bindProgress()\n*/\nvar AmplitudeEvents = (function () {\n\t/*--------------------------------------------------------------------------\n\t\tInitializes the handlers for the events listened to by Amplitude\n\t--------------------------------------------------------------------------*/\n\tfunction initializeEvents(){\n\t\t/*\n\t\t\tWrite out debug message\n\t\t*/\n\t\tAmplitudeHelpers.writeDebugMessage( 'Beginning initialization of event handlers..' );\n\n\t\t/*\n\t\t\tSets flag that the screen is moving and not a tap\n\t\t*/\n\t\tdocument.addEventListener('touchmove', function(){\n\t\t\tconfig.is_touch_moving = true;\n\t\t});\n\n\t\t/*\n\t\t\tOn touch end if it was a touch move event, set moving to\n\t\t\tfalse\n\t\t*/\n\t\tdocument.addEventListener('touchend', function(){\n\t\t\tif( config.is_touch_moving ){\n\t\t\t\tconfig.is_touch_moving = false;\n\t\t\t}\n\t\t});\n\n\t\t/*\n\t\t\tOn time update for the audio element, update visual displays that\n\t\t\trepresent the time on either a visualized element or time display.\n\t\t*/\n\t\tbindTimeUpdate();\n\n\t\t/*\n\t\t\tBinds key down event handlers for matching key codes to functions.\n\t\t*/\n\t\tbindKeyDownEventHandlers();\n\n\t\t/*\n\t\t\tWhen the audio element has ended playing, we handle the song\n\t\t\tending. In a single song or multiple modular song instance,\n\t\t\tthis just synchronizes the visuals for time and song time\n\t\t\tvisualization, but for a playlist it determines whether\n\t\t\tit should play the next song or not.\n\t\t*/\n\t\tbindSongEnded();\n\n\t\t/*\n\t\t\tBinds progress event so we can see how much of the song is loaded.\n\t\t*/\n\t\tbindProgress();\n\n\t\t/*\n\t\t\tBinds 'amplitude-play' event handlers\n\t\t*/\n\t\tbindPlay();\n\n\t\t/*\n\t\t\tBinds 'amplitude-pause' event handlers.\n\t\t*/\n\t\tbindPause();\n\n\t\t/*\n\t\t\tBinds 'amplitude-play-pause' event handlers.\n\t\t*/\n\t\tbindPlayPause();\n\n\t\t/*\n\t\t\tBinds 'amplitude-stop' event handlers.\n\t\t*/\n\t\tbindStop();\n\n\t\t/*\n\t\t\tBinds 'amplitude-mute' event handlers.\n\t\t*/\n\t\tbindMute();\n\n\t\t/*\n\t\t\tBinds 'amplitude-volume-up' event handlers\n\t\t*/\n\t\tbindVolumeUp();\n\n\t\t/*\n\t\t\tBinds 'amplitude-volume-down' event handlers\n\t\t*/\n\t\tbindVolumeDown();\n\n\t\t/*\n\t\t\tBinds 'amplitude-song-slider' event handlers\n\t\t*/\n\t\tbindSongSlider();\n\n\t\t/*\n\t\t\tBinds 'amplitude-volume-slider' event handlers.\n\t\t*/\n\t\tbindVolumeSlider();\n\n\t\t/*\n\t\t\tBinds 'amplitude-next' event handlers.\n\t\t*/\n\t\tbindNext();\n\n\t\t/*\n\t\t\tBinds 'amplitude-prev' event handlers.\n\t\t*/\n\t\tbindPrev();\n\n\t\t/*\n\t\t\tBinds 'amplitude-shuffle' event handlers.\n\t\t*/\n\t\tbindShuffle();\n\n\t\t/*\n\t\t\tBinds 'amplitude-repeat' event handlers.\n\t\t*/\n\t\tbindRepeat();\n\n\t\t/*\n\t\t\tBinds 'amplitude-playback-speed' event handlers.\n\t\t*/\n\t\tbindPlaybackSpeed();\n\n\t\t/*\n\t\t\tBinds 'amplitude-skip-to' event handlers.\n\t\t*/\n\t\tbindSkipTo();\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tOn time update for the audio element, update visual displays that\n\t\t\trepresent the time on either a visualized element or time display.\n\t--------------------------------------------------------------------------*/\n\tfunction bindTimeUpdate(){\n\t\tconfig.active_song.removeEventListener( 'timeupdate', AmplitudeHandlers.updateTime );\n\t\tconfig.active_song.addEventListener( 'timeupdate', AmplitudeHandlers.updateTime );\n\n // also bind change of duratuion\n\t\tconfig.active_song.removeEventListener( 'durationchange', AmplitudeHandlers.updateTime );\n\t\tconfig.active_song.addEventListener( 'durationchange', AmplitudeHandlers.updateTime );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tOn keydown, we listen to what key got pressed so we can map the key to\n\t\ta function. This allows the user to map pause and play, next, etc. to key\n\t\tpresses.\n\t--------------------------------------------------------------------------*/\n\tfunction bindKeyDownEventHandlers(){\n\t\tdocument.removeEventListener(\"keydown\", AmplitudeHelpers.keydown );\n\t\tdocument.addEventListener(\"keydown\", AmplitudeHandlers.keydown );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tWhen the audio element has ended playing, we handle the song\n\t\tending. In a single song or multiple modular song instance,\n\t\tthis just synchronizes the visuals for time and song time\n\t\tvisualization, but for a playlist it determines whether\n\t\tit should play the next song or not.\n\t--------------------------------------------------------------------------*/\n\tfunction bindSongEnded(){\n\t\tconfig.active_song.removeEventListener( 'ended', AmplitudeHandlers.songEnded );\n\t\tconfig.active_song.addEventListener( 'ended', AmplitudeHandlers.songEnded );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tAs the audio is loaded, the progress event gets fired. We bind into this\n\t\tto grab the buffered percentage of the song. We can then add more elements\n\t\tto show the buffered amount.\n\t--------------------------------------------------------------------------*/\n\tfunction bindProgress(){\n\t\tconfig.active_song.removeEventListener( 'progress', AmplitudeHandlers.progess );\n\t\tconfig.active_song.addEventListener( 'progress', AmplitudeHandlers.progress );\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-play\"\n\n\t\tBinds click and touchend events for amplitude play buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPlay(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-play\n\t\t*/\n\t\tvar play_classes = document.getElementsByClassName(\"amplitude-play\");\n\n\t\t/*\n\t\t\tIterates over all of the play classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < play_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( navigator.userAgent ) ) {\n\t\t\t\tplay_classes[i].removeEventListener('touchend', AmplitudeHandlers.play );\n\t\t\t\tplay_classes[i].addEventListener('touchend', AmplitudeHandlers.play );\n\t\t\t}else{\n\t\t\t\tplay_classes[i].removeEventListener('click', AmplitudeHandlers.play );\n\t\t\t\tplay_classes[i].addEventListener('click', AmplitudeHandlers.play );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-pause\"\n\n\t\tBinds click and touchend events for amplitude pause buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPause(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-pause\n\t\t*/\n\t\tvar pause_classes = document.getElementsByClassName(\"amplitude-pause\");\n\n\t\t/*\n\t\t\tIterates over all of the pause classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < pause_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tpause_classes[i].removeEventListener('touchend', AmplitudeHandlers.pause );\n\t\t\t\tpause_classes[i].addEventListener('touchend', AmplitudeHandlers.pause );\n\t\t\t}else{\n\t\t\t\tpause_classes[i].removeEventListener('click', AmplitudeHandlers.pause );\n\t\t\t\tpause_classes[i].addEventListener('click', AmplitudeHandlers.pause );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-play-pause\"\n\n\t\tBinds click and touchend events for amplitude play pause buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPlayPause(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-play-pause\n\t\t*/\n\t\tvar play_pause_classes = document.getElementsByClassName(\"amplitude-play-pause\");\n\n\t\t/*\n\t\t\tIterates over all of the play/pause classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < play_pause_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tplay_pause_classes[i].removeEventListener('touchend', AmplitudeHandlers.playPause );\n\t\t\t\tplay_pause_classes[i].addEventListener('touchend', AmplitudeHandlers.playPause );\n\t\t\t}else{\n\t\t\t\tplay_pause_classes[i].removeEventListener('click', AmplitudeHandlers.playPause );\n\t\t\t\tplay_pause_classes[i].addEventListener('click', AmplitudeHandlers.playPause );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-stop\"\n\n\t\tBinds click and touchend events for amplitude stop buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindStop(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-stop\n\t\t*/\n\t\tvar stop_classes = document.getElementsByClassName(\"amplitude-stop\");\n\n\t\t/*\n\t\t\tIterates over all of the stop classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < stop_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tstop_classes[i].removeEventListener('touchend', AmplitudeHandlers.stop );\n\t\t\t\tstop_classes[i].addEventListener('touchend', AmplitudeHandlers.stop );\n\t\t\t}else{\n\t\t\t\tstop_classes[i].removeEventListener('click', AmplitudeHandlers.stop );\n\t\t\t\tstop_classes[i].addEventListener('click', AmplitudeHandlers.stop );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-mute\"\n\n\t\tBinds click and touchend events for amplitude mute buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindMute(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitue-mute\n\t\t*/\n\t\tvar mute_classes = document.getElementsByClassName(\"amplitude-mute\");\n\n\t\t/*\n\t\t\tIterates over all of the mute classes and binds the event interaction\n\t\t\tmethod to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < mute_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\t/*\n\t\t\t\t\tChecks for an iOS device and displays an error message if debugging\n\t\t\t\t\tis turned on.\n\t\t\t\t*/\n\t\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t\t}else{\n\t\t\t\t\tmute_classes[i].removeEventListener('touchend', AmplitudeHandlers.mute );\n\t\t\t\t\tmute_classes[i].addEventListener('touchend', AmplitudeHandlers.mute );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tmute_classes[i].removeEventListener('click', AmplitudeHandlers.mute );\n\t\t\t\tmute_classes[i].addEventListener('click', AmplitudeHandlers.mute );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-volume-up\"\n\n\t\tBinds click and touchend events for amplitude volume up buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindVolumeUp(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-volume-up\n\t\t*/\n\t\tvar volume_up_classes = document.getElementsByClassName(\"amplitude-volume-up\");\n\n\t\t/*\n\t\t\tIterates over all of the volume up classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < volume_up_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\t/*\n\t\t\t\t\tChecks for an iOS device and displays an error message if debugging\n\t\t\t\t\tis turned on.\n\t\t\t\t*/\n\t\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t\t}else{\n\t\t\t\t\tvolume_up_classes[i].removeEventListener('touchend', AmplitudeHandlers.volumeUp );\n\t\t\t\t\tvolume_up_classes[i].addEventListener('touchend', AmplitudeHandlers.volumeUp );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tvolume_up_classes[i].removeEventListener('click', AmplitudeHandlers.volumeUp );\n\t\t\t\tvolume_up_classes[i].addEventListener('click', AmplitudeHandlers.volumeUp );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-volume-down\"\n\n\t\tBinds click and touchend events for amplitude volume down buttons\n\t--------------------------------------------------------------------------*/\n\tfunction bindVolumeDown(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-volume-down\n\t\t*/\n\t\tvar volume_down_classes = document.getElementsByClassName(\"amplitude-volume-down\");\n\n\t\t/*\n\t\t\tIterates over all of the volume down classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < volume_down_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\t/*\n\t\t\t\t\tChecks for an iOS device and displays an error message if debugging\n\t\t\t\t\tis turned on.\n\t\t\t\t*/\n\t\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t\t}else{\n\t\t\t\t\tvolume_down_classes[i].removeEventListener('touchend', AmplitudeHandlers.volumeDown );\n\t\t\t\t\tvolume_down_classes[i].addEventListener('touchend', AmplitudeHandlers.volumeDown );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tvolume_down_classes[i].removeEventListener('click', AmplitudeHandlers.volumeDown );\n\t\t\t\tvolume_down_classes[i].addEventListener('click', AmplitudeHandlers.volumeDown );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-song-slider\"\n\n\t\tBinds change and input events for amplitude song slider inputs\n\t--------------------------------------------------------------------------*/\n\tfunction bindSongSlider(){\n\t\t/*\n\t\t\tGets browser so if we need to apply overrides, like we usually\n\t\t\thave to do for anything cool in IE, we can do that.\n\t\t*/\n\t\tvar ua \t\t= window.navigator.userAgent;\n var msie \t= ua.indexOf(\"MSIE \");\n\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-song-slider\n\t\t*/\n\t\tvar song_sliders = document.getElementsByClassName(\"amplitude-song-slider\");\n\n\t\t/*\n\t\t\tIterates over all of the song slider classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is IE we listen to the change event\n\t\t\twhere if it is anything else, it's the input method.\n\t\t*/\n\t\tfor( var i = 0; i < song_sliders.length; i++ ){\n\t\t\tif ( msie > 0 || !!navigator.userAgent.match(/Trident.*rv\\:11\\./) ){\n\t\t\t\tsong_sliders[i].removeEventListener('change', AmplitudeHandlers.songSlider );\n\t\t\t\tsong_sliders[i].addEventListener('change', AmplitudeHandlers.songSlider );\n\t\t\t}else{\n\t\t\t\tsong_sliders[i].removeEventListener('input', AmplitudeHandlers.songSlider );\n\t\t\t\tsong_sliders[i].addEventListener('input', AmplitudeHandlers.songSlider );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-volume-slider\"\n\n\t\tBinds change and input events for amplitude volume slider inputs\n\t--------------------------------------------------------------------------*/\n\tfunction bindVolumeSlider(){\n\t\t/*\n\t\t\tGets browser so if we need to apply overrides, like we usually\n\t\t\thave to do for anything cool in IE, we can do that.\n\t\t*/\n\t\tvar ua \t\t= window.navigator.userAgent;\n var msie \t= ua.indexOf(\"MSIE \");\n\n /*\n\t\t\tGets all of the elements with the class amplitude-volume-slider\n */\n\t\tvar volume_sliders = document.getElementsByClassName(\"amplitude-volume-slider\");\n\n\t\t/*\n\t\t\tIterates over all of the volume slider classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is IE we listen to the change event\n\t\t\twhere if it is anything else, it's the input method.\n\t\t*/\n\t\tfor( var i = 0; i < volume_sliders.length; i++ ){\n\t\t\t/*\n\t\t\t\tWARNING: If iOS, we don't do anything because iOS does not allow the\n\t\t\t\tvolume to be adjusted through anything except the buttons on the side of\n\t\t\t\tthe device.\n\t\t\t*/\n\t\t\tif( /iPhone|iPad|iPod/i.test(navigator.userAgent) ) {\n\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'iOS does NOT allow volume to be set through javascript: https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW4' );\n\t\t\t}else{\n\t\t\t\tif ( msie > 0 || !!navigator.userAgent.match(/Trident.*rv\\:11\\./) ){\n\t\t\t\t\tvolume_sliders[i].removeEventListener('change', AmplitudeHandlers.volumeSlider );\n\t\t\t\t\tvolume_sliders[i].addEventListener('change', AmplitudeHandlers.volumeSlider );\n\t\t\t\t}else{\n\t\t\t\t\tvolume_sliders[i].removeEventListener('input', AmplitudeHandlers.volumeSlider );\n\t\t\t\t\tvolume_sliders[i].addEventListener('input', AmplitudeHandlers.volumeSlider );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-next\"\n\n\t\tBinds click and touchend events for amplitude next buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindNext(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-next\n */\n\t\tvar next_classes = document.getElementsByClassName(\"amplitude-next\");\n\n\t\t/*\n\t\t\tIterates over all of the next classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < next_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tnext_classes[i].removeEventListener('touchend', AmplitudeHandlers.next );\n\t\t\t\tnext_classes[i].addEventListener('touchend', AmplitudeHandlers.next );\n\t\t\t}else{\n\t\t\t\tnext_classes[i].removeEventListener('click', AmplitudeHandlers.next );\n\t\t\t\tnext_classes[i].addEventListener('click', AmplitudeHandlers.next );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-prev\"\n\n\t\tBinds click and touchend events for amplitude prev buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPrev(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-prev\n\t\t*/\n\t\tvar prev_classes = document.getElementsByClassName(\"amplitude-prev\");\n\n\t\t/*\n\t\t\tIterates over all of the prev classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < prev_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tprev_classes[i].removeEventListener('touchend', AmplitudeHandlers.prev );\n\t\t\t\tprev_classes[i].addEventListener('touchend', AmplitudeHandlers.prev );\n\t\t\t}else{\n\t\t\t\tprev_classes[i].removeEventListener('click', AmplitudeHandlers.prev );\n\t\t\t\tprev_classes[i].addEventListener('click', AmplitudeHandlers.prev );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-shuffle\"\n\n\t\tBinds click and touchend events for amplitude shuffle buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindShuffle(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-shuffle\n\t\t*/\n\t\tvar shuffle_classes = document.getElementsByClassName(\"amplitude-shuffle\");\n\n\t\t/*\n\t\t\tIterates over all of the shuffle classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < shuffle_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tSince we are re-binding everything we remove any classes that signify\n\t\t\t\ta state of the shuffle control.\n\t\t\t*/\n\t\t\tshuffle_classes[i].classList.remove('amplitude-shuffle-on');\n\t\t\tshuffle_classes[i].classList.add('amplitude-shuffle-off');\n\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tshuffle_classes[i].removeEventListener('touchend', AmplitudeHandlers.shuffle );\n\t\t\t\tshuffle_classes[i].addEventListener('touchend', AmplitudeHandlers.shuffle );\n\t\t\t}else{\n\t\t\t\tshuffle_classes[i].removeEventListener('click', AmplitudeHandlers.shuffle );\n\t\t\t\tshuffle_classes[i].addEventListener('click', AmplitudeHandlers.shuffle );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-repeat\"\n\n\t\tBinds click and touchend events for amplitude repeat buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindRepeat(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-repeat\n\t\t*/\n\t\tvar repeat_classes = document.getElementsByClassName(\"amplitude-repeat\");\n\n\t\t/*\n\t\t\tIterates over all of the repeat classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < repeat_classes.length; i++ ){\n\t\t\t/*\n\t\t\t\tSince we are re-binding everything we remove any classes that signify\n\t\t\t\ta state of the repeat control.\n\t\t\t*/\n\t\t\trepeat_classes[i].classList.remove('amplitude-repeat-on');\n\t\t\trepeat_classes[i].classList.add('amplitude-repeat-off');\n\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\trepeat_classes[i].removeEventListener('touchend', AmplitudeHandlers.repeat );\n\t\t\t\trepeat_classes[i].addEventListener('touchend', AmplitudeHandlers.repeat );\n\t\t\t}else{\n\t\t\t\trepeat_classes[i].removeEventListener('click', AmplitudeHandlers.repeat );\n\t\t\t\trepeat_classes[i].addEventListener('click', AmplitudeHandlers.repeat );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-playback-speed\"\n\n\t\tBinds click and touchend events for amplitude playback speed buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindPlaybackSpeed(){\n\t\t/*\n\t\t\tGets all of the elements with the class amplitude-playback-speed\n\t\t*/\n\t\tvar playback_speed_classes = document.getElementsByClassName(\"amplitude-playback-speed\");\n\n\t\t/*\n\t\t\tIterates over all of the playback speed classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it is click.\n\t\t*/\n\t\tfor( var i = 0; i < playback_speed_classes.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tplayback_speed_classes[i].removeEventListener('touchend', AmplitudeHandlers.playbackSpeed );\n\t\t\t\tplayback_speed_classes[i].addEventListener('touchend', AmplitudeHandlers.playbackSpeed );\n\t\t\t}else{\n\t\t\t\tplayback_speed_classes[i].removeEventListener('click', AmplitudeHandlers.playbackSpeed );\n\t\t\t\tplayback_speed_classes[i].addEventListener('click', AmplitudeHandlers.playbackSpeed );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tBINDS: class=\"amplitude-skip-to\"\n\n\t\tBinds click and touchend events for amplitude skip to buttons.\n\t--------------------------------------------------------------------------*/\n\tfunction bindSkipTo(){\n\t\t/*\n\t\t\tGets all of the skip to elements with the class 'amplitude-skip-to'\n\t\t*/\n\t\tvar skipToClasses = document.getElementsByClassName(\"amplitude-skip-to\");\n\n\t\t/*\n\t\t\tIterates over all of the skip to classes and binds the event interaction\n\t\t\tmethods to the element. If the browser is mobile, then the event is touchend\n\t\t\totherwise it's a click.\n\t\t*/\n\t\tfor( var i = 0; i < skipToClasses.length; i++ ){\n\t\t\tif( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {\n\t\t\t\tskipToClasses[i].removeEventListener('touchend', AmplitudeHandlers.skipTo );\n\t\t\t\tskipToClasses[i].addEventListener('touchend', AmplitudeHandlers.skipTo );\n\t\t\t}else{\n\t\t\t\tskipToClasses[i].removeEventListener('click', AmplitudeHandlers.skipTo );\n\t\t\t\tskipToClasses[i].addEventListener('click', AmplitudeHandlers.skipTo );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tinitializeEvents: initializeEvents\n\t}\n})();\n\nexport default AmplitudeEvents\n\n\n\n// WEBPACK FOOTER //\n// ./src/events/events.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the Amplitude Visual Sync module\n * @module visual/AmplitudeVisualSync\n */\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * Imports the Amplitude Core module\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * Imports the Amplitude Core Helpers module\n * @module core/AmplitudeCoreHelpers\n */\nimport AmplitudeCoreHelpers from '../core/helpers.js';\n\n/**\n * These methods help handle interactions whether it's computation or shuffling\n * songs.\n *\n * @module events/AmplitudeEventsHelpers\n */\nlet AmplitudeEventsHelpers = (function() {\n\t/**\n\t * Computes the current song time. Breaks down where the song is into\n\t * hours, minutes, seconds and formats it to be displayed to the user.\n\t *\n\t * @access public\n\t */\n\tfunction computeCurrentTimes(){\n\t\t/*\n\t\t\tInitialize the current time object that will be returned.\n\t\t*/\n\t\tlet currentTime = {};\n\n\t\t/*\n\t\t\tComputes the current seconds for the song.\n\t\t*/\n\t\tlet currentSeconds = ( Math.floor( config.active_song.currentTime % 60 ) < 10 ? '0' : '' ) +\n\t\t\t\t\t\t\t Math.floor( config.active_song.currentTime % 60 );\n\n\t\t/*\n\t\t\tComputes the current minutes for the song.\n\t\t*/\n\t\tlet currentMinutes = Math.floor( config.active_song.currentTime / 60 );\n\n\t\t/*\n\t\t\tInitialize the current hours variable.\n\t\t*/\n\t\tlet currentHours = '00';\n\n\t\t/*\n\t\t\tIf the current minutes is less than 10, we add a leading 0.\n\t\t*/\n\t\tif( currentMinutes < 10 ){\n\t\t\tcurrentMinutes = '0'+currentMinutes;\n\t\t}\n\n\t\t/*\n\t\t\tIf the user is more than 60 minutes into the song, then\n\t\t\twe extract the hours.\n\t\t*/\n\t\tif( currentMinutes >= 60 ){\n\t\t\tcurrentHours \t\t= Math.floor( currentMinutes / 60 );\n\t\t\tcurrentMinutes \t\t= currentMinutes % 60;\n\n\t\t\t/*\n\t\t\t\tIf the user is less than 10 minutes in, we append the\n\t\t\t\tadditional 0 to the minutes.\n\t\t\t*/\n\t\t\tif( currentMinutes < 10 ){\n\t\t\t\tcurrentMinutes = '0'+currentMinutes;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tBuild a clean current time object and send back the appropriate information.\n\t\t*/\n\t\tcurrentTime.seconds = currentSeconds;\n\t\tcurrentTime.minutes = currentMinutes;\n\t\tcurrentTime.hours \t= currentHours;\n\n\t\treturn currentTime;\n\t}\n\n\t/**\n\t * Computes the current song duration. Breaks down where the song is into\n\t * hours, minutes, seconds and formats it to be displayed to the user.\n\t *\n\t * @access public\n\t */\n\tfunction computeSongDuration(){\n\t\t/*\n\t\t\tInitialize the song duration object that will be returned.\n\t\t*/\n\t\tlet songDuration = {};\n\n\t\t/*\n\t\t\tComputes the duration of the song's seconds.\n\t\t*/\n\t\tlet songDurationSeconds = ( Math.floor( config.active_song.duration % 60 ) < 10 ? '0' : '' ) +\n\t\t\t\t\t\t\t\t\t \t\tMath.floor( config.active_song.duration % 60 );\n\n\t\t/*\n\t\t\tComputes the duration of the song's minutes.\n\t\t*/\n\t\tlet songDurationMinutes = Math.floor( config.active_song.duration / 60 );\n\n\t\t/*\n\t\t\tInitialize the hours duration variable.\n\t\t*/\n\t\tvar songDurationHours = '0';\n\n\t\t/*\n\t\t\tIf the song duration minutes is less than 10, we add a leading 0.\n\t\t*/\n\t\tif( songDurationMinutes < 10 ){\n\t\t\tsongDurationMinutes = '0'+songDurationMinutes;\n\t\t}\n\n\t\t/*\n\t\t\tIf there is more than 60 minutes in the song, then we\n\t\t\textract the hours.\n\t\t*/\n\t\tif( songDurationMinutes >= 60 ){\n\t\t\tsongDurationHours \t\t= Math.floor( songDurationMinutes / 60 );\n\t\t\tsongDurationMinutes \t= songDurationMinutes % 60;\n\n\t\t\t/*\n\t\t\t\tIf the song duration minutes is less than 10 we append\n\t\t\t\tthe additional 0.\n\t\t\t*/\n\t\t\tif( songDurationMinutes < 10 ){\n\t\t\t\tsongDurationMinutes = '0'+songDurationMinutes;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tBuild a clean song duration object and send back the appropriate information.\n\t\t*/\n\t\tsongDuration.seconds \t= songDurationSeconds;\n\t\tsongDuration.minutes \t= songDurationMinutes;\n\t\tsongDuration.hours \t\t= songDurationHours;\n\n\t\treturn songDuration;\n\t}\n\n\t/**\n\t * Computes the song completion percentage.\n\t *\n\t * @access public\n\t */\n\tfunction computeSongCompletionPercentage(){\n\t\treturn ( config.active_song.currentTime / config.active_song.duration ) * 100;\n\t}\n\n\t/**\n\t * Sets the current song's playback speed\n\t *\n\t * @access public\n\t * @param {number} speed \t- The float with a base of 1 representing the speed\n\t *\n\t */\n\tfunction setPlaybackSpeed( speed ){\n\t\tAmplitudeCore.setPlaybackSpeed( speed );\n\t}\n\n\t/**\n\t * Sets the state of the repeat for the current song.\n\t *\n\t * @access public\n\t * @param {boolean} repeat - A boolean representing whether the repeat should be on or off\n\t * @param {string} playlist - The key of the playlist for repeating\n\t */\n\tfunction setRepeat( repeat, playlist ){\n\t\t/*\n\t\t If the playlist is null, then we are dealing with the global\n\t\t repeat status.\n\t\t*/\n\t\tif( playlist == null ){\n\t\t\t/*\n\t\t\t\tSet the global repeat to be toggled\n\t\t\t*/\n\t\t\tconfig.repeat = repeat;\n\n\t\t\t/*\n\t\t\t\tVisually sync repeat\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncRepeat();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tSet the playlist repeat to be toggled.\n\t\t\t*/\n\t\t\tconfig.repeat_statuses[playlist] = repeat;\n\n\t\t\t/*\n\t\t\t\tVisually sync playlist repeat\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncRepeatPlaylist( playlist );\n\t\t}\n\n\n/** When song ends and in playlis mode and done with playlist check repeat **/\n\n\n\t}\n\n\n\t/**\n\t * Sets the state of the repeat song\n\t *\n\t * @access public\n\t * @param {boolean} repeat - A boolean representing whether the repeat shoudl be on or off for the song.\n\t */\n\t function setRepeatSong( repeat ){\n\t\t config.repeat_song = repeat;\n\t }\n\n\t/**\n\t * Sets the main play pause buttons to the current state of the song.\n\t *\n\t * @access public\n\t */\n\tfunction setMainPlayPause(){\n\t\t/*\n\t\t\tDetermines what action we should take based on the\n\t\t\tstate of the song.\n\t\t*/\n\t\tif( config.active_song.paused ){\n\t\t\t/*\n\t\t\t\tThe song was paused so we sync visually for the song\n\t\t\t\tthat is playing and we play the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of playing.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\tto be paused and we pause the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of paused.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t/*\n\t\t\t\tPause the song\n\t\t\t*/\n\t\t\tAmplitudeCore.pause();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the playlist main play pause buttons to the current state of the song.\n\t *\n\t * @access public\n\t * @param {string} playlist The playlist the main play pause button controls\n\t */\n\tfunction setPlaylistPlayPause( playlist ){\n\t\t/*\n\t\t\tThe only thing that can change when you click a playlist\n\t\t\tplay pause is the playlist. Main play pauses have no change\n\t\t\tin song, song play pauses can change playlist and song.\n\t\t*/\n\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\t\t\t/*\n\t\t\t\tPlay first song in the playlist since we just\n\t\t\t\tswitched playlists, we start from the first song.\n\n\t\t\t\tIf the user has shuffle on for the playlist, then\n\t\t\t\twe go from the first song in the shuffle playlist array.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[playlist] ){\n\t\t\t\tAmplitudeCoreHelpers.changeSong( config.shuffled_playlists[playlist][0].original_index );\n\t\t\t}else{\n\t\t\t\tAmplitudeCoreHelpers.changeSong( config.playlists[playlist][0] );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDetermines what action we should take based on the\n\t\t\tstate of the song.\n\t\t*/\n\t\tif( config.active_song.paused ){\n\t\t\t/*\n\t\t\t\tThe song was paused so we sync visually for the song\n\t\t\t\tthat is playing and we play the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of playing.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\tto be paused and we pause the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of paused.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t/*\n\t\t\t\tPause the song\n\t\t\t*/\n\t\t\tAmplitudeCore.pause();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the song play pause buttons to the current state of the song.\n\t *\n\t * @access public\n\t * @param {string} playlist The playlist the song is a part of\n\t * @param {number} songIndex The index of the song being played/paused\n\t *\n\t */\n\tfunction setSongPlayPause( playlist, songIndex ){\n\t\t/*\n\t\t\tThere can be multiple playlists on the page and there can be\n\t\t\tmultiple songs on the page AND there can be songs in multiple\n\t\t\tplaylists, so we have some checking to do.\n\t\t*/\n\n\t\t/*\n\t\t\tCheck to see if the playlist has changed. If it has,\n\t\t\tset the active playlist.\n\t\t*/\n\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\t\t\t/*\n\t\t\t\tIf there's a new playlist then we reset the\n\t\t\t\tsong since the song could be in 2 playlists,\n\t\t\t\tbut the user selects another playlist.\n\t\t\t*/\n\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t}\n\n\t\t/*\n\t\t\tCheck to see if the song has changed. If it has,\n\t\t\tset the active song. If it was in a playlist, the\n\t\t\tsong wouldn't change here, since we already set the\n\t\t\tsong when we checked for a playlist.\n\t\t*/\n\t\tif( AmplitudeCoreHelpers.checkNewSong( songIndex ) ){\n\t\t\t/*\n\t\t\t\tThe song selected is different, so we change the\n\t\t\t\tsong.\n\t\t\t*/\n\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t}\n\n\t\t/*\n\t\t\tDetermines what action we should take based on the\n\t\t\tstate of the song.\n\t\t*/\n\t\tif( config.active_song.paused ){\n\t\t\t/*\n\t\t\t\tThe song was paused so we sync visually for the song\n\t\t\t\tthat is playing and we play the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of playing.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'playing' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'playing' );\n\n\t\t\t/*\n\t\t\t\tPlay the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}else{\n\t\t\t/*\n\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\tto be paused and we pause the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t/*\n\t\t\t\tIf there is an active playlist, then\n\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\tbutton to the state of paused.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t/*\n\t\t\t\tSync the song play pause buttons\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t/*\n\t\t\t\tPause the song\n\t\t\t*/\n\t\t\tAmplitudeCore.pause();\n\t\t}\n\t}\n\n\t/**\n\t * Sets the shuffle state for a playlist\n\t *\n\t * @access public\n\t * @param {string} playlist - The playlist being shuffled\n\t */\n\tfunction setShuffle( playlist ){\n\t\t/*\n\t\t\tIf the playlist is null, then we are dealing with the global\n\t\t\tshuffle status.\n\t\t*/\n\t\tif( playlist == null ){\n\t\t\t/*\n\t\t\t\tIf shuffle is on, we toggle it off. If shuffle is off, we\n\t\t\t\ttoggle on.\n\t\t\t*/\n\t\t\tif( config.shuffle_on ){\n\t\t\t\tconfig.shuffle_on \t= false;\n\t\t\t\tconfig.shuffle_list = {};\n\t\t\t}else{\n\t\t\t\tconfig.shuffle_on = true;\n\t\t\t\tAmplitudeCoreHelpers.shuffleSongs();\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tVisually sync the shuffle statuses\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncShuffle( config.shuffle_on );\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the playlist shuffled is on, we toggle it off. If the\n\t\t\t\tplaylist shuffled is off, we toggle it on.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[playlist] ){\n\t\t\t\tconfig.shuffled_statuses[playlist] = false;\n\t\t\t\tconfig.shuffled_playlists[playlist] = [];\n\t\t\t}else{\n\t\t\t\tconfig.shuffled_statuses[playlist] = true;\n\t\t\t\tAmplitudeCoreHelpers.shufflePlaylistSongs( playlist );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tVisually sync the playlist shuffle statuses.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaylistShuffle( config.shuffled_statuses[playlist], playlist );\n\t\t}\n\t}\n\n\t/**\n\t * Sets the next song when next is clicked\n\t *\n\t * @access public\n\t * @param {boolean} [songEnded=false] If the song ended, this is set to true\n\t * so we take into effect the repeat setting.\n\t*/\n\tfunction setNext( songEnded = false ){\n\t\t/*\n\t\t\tInitializes the next index variable. This will be the\n\t\t\tindex of the song that is next.\n\t\t*/\n\t\tlet nextIndex = 0;\n /*\n Ensure we don't loop in the playlist if config.repeat is not true\n */\n\t\tlet endOfList = false;\n\n\t\tif( config.repeat_song ){\n\t\t\t/*\n\t\t\t\tIf the playlist is shuffled, get the now playing index.\n\t\t\t*/\n\t\t\tif( config.shuffle_on ){\n\t\t\t\tnextIndex = config.shuffle_active_index;\n\t\t\t}else{\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}else{\n\n\t\t\t/*\n\t\t\t\tIf the shuffle is on, we use the shuffled list of\n\t\t\t\tsongs to determine our next song.\n\t\t\t*/\n\t\t\tif( config.shuffle_on ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active shuffle index + 1 is less than the length, then\n\t\t\t\t\twe use the next shuffle otherwise we go to the beginning\n\t\t\t\t\tof the shuffle list.\n\t\t\t\t*/\n\t\t\t\tif( ( parseInt( config.shuffle_active_index ) + 1 ) < config.shuffle_list.length ){\n\t\t\t\t\tconfig.shuffle_active_index = parseInt( config.shuffle_active_index ) + 1;\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the next index to be the index of the song in the shuffle list.\n\t\t\t\t\t*/\n\t\t\t\t\tnextIndex = config.shuffle_list[ parseInt( config.shuffle_active_index ) ].original_index;\n\t\t\t\t}else{\n\t\t\t\t\tconfig.shuffle_active_index = 0;\n\t\t\t\t\tnextIndex = 0;\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active index + 1 is less than the length of the songs, then\n\t\t\t\t\twe use the next song otherwise we go to the beginning of the\n\t\t\t\t\tsong list.\n\t\t\t\t*/\n\t\t\t\tif( ( parseInt( config.active_index ) + 1 ) < config.songs.length ){\n\t\t\t\t\tconfig.active_index = parseInt( config.active_index ) + 1;\n\t\t\t\t}else{\n\t\t\t\t\tconfig.active_index = 0;\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t\tSets the next index.\n\t\t\t\t*/\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChange the song to the index we need.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( nextIndex );\n\n\n\t\t/*\n\t\t\tIf it's the end of the list and repeat is not on, do nothing.\n\t\t*/\n\t\tif( endOfList && !config.repeat ){\n\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the song has ended and repeat is on, play the song.\n\t\t\t*/\n\t if( !( songEnded && !config.repeat && endOfList ) ){\n\t \tAmplitudeCore.play();\n\t }\n\t\t}\n\n /*\n \tSyncs the main play pause button, playlist play pause button and\n \tsong play pause.\n */\n\t\tAmplitudeVisualSync.syncMainPlayPause( );\n\t\tAmplitudeVisualSync.syncSongPlayPause( null, nextIndex);\n\n /*\n \tCall after next callback\n */\n AmplitudeCoreHelpers.runCallback('after_next');\n\n\t\t/*\n\t\t\tIf we are repeating the song, call the song repeated callback\n\t\t*/\n\t\tif( config.repeat_song ){\n\t\t\tAmplitudeCoreHelpers.runCallback('song_repeated');\n\t\t}\n\t}\n\n\t/**\n\t * Sets the next song in a playlist\n\t *\n\t * @param {string} playlist - The playlist being shuffled\n\t * @param {boolean} [songEnded=false] - If the song ended, this is set to true\n\t * so we take into effect the repeat setting.\n\t */\n\tfunction setNextPlaylist( playlist, songEnded = false ){\n\t\t/*\n\t\t\tInitializes the next index\n\t\t*/\n\t\tlet nextIndex = 0;\n\n /*\n Used to determine whether the playlist looped over\n If it did, only play if repeat is allowed, end otherwise\n @TODO: Different settings for song loop, in-playlist loop and global loop\n */\n\t\tlet endOfList = false;\n\n\t\t/*\n\t\t\tIf we are repeating the song, then we just start the song over.\n\t\t*/\n\n\t\tif( config.repeat_song ){\n\t\t\t/*\n\t\t\t\tIf the playlist is shuffled, get the now playing index.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[ playlist ] ){\n\t\t\t\tnextIndex = config.shuffled_playlists[ playlist ][ config.shuffled_active_indexes[ playlist ] ].original_index;\n\t\t\t}else{\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the playlist is shuffled we get the next index of the playlist.\n\t\t\t*/\n\t\t\tif( config.shuffled_statuses[ playlist ] ){\n\t\t\t\t/*\n\t\t\t\t\tGets the shuffled playlist's active song index.\n\t\t\t\t*/\n\t\t\t\tlet shuffledPlaylistActiveSongIndex = parseInt( config.shuffled_active_indexes[ playlist ] );\n\n\t\t\t\t/*\n\t\t\t\t\tIf the index + 1 is less than the length of the playlist, we increment\n\t\t\t\t\tthe next index otherwise we take the first index of 0.\n\t\t\t\t*/\n\t\t\t\tif( shuffledPlaylistActiveSongIndex + 1 < config.shuffled_playlists[ playlist ].length ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the shuffled playlist active song index.\n\t\t\t\t\t*/\n\t\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = shuffledPlaylistActiveSongIndex + 1;\n\t\t\t\t\t/*\n\t\t\t\t\t\tGet the index of the song that we will be switching to.\n\t\t\t\t\t*/\n\t\t\t\t\tnextIndex = config.shuffled_playlists[ playlist ][ config.shuffled_active_indexes[ playlist ] ].original_index;\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets the active shuffled playlist active index to 0 and gets the original index of\n\t\t\t\t\t\tthe song at the shuffled index of 0.\n\t\t\t\t\t*/\n\t\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = 0;\n\t\t\t\t\tnextIndex = config.shuffled_playlists[ playlist ][0].original_index;\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the index of the active song within the scope\n\t\t\t\t\tof the playlist.\n\t\t\t\t*/\n\t\t\t\tlet playlistActiveSongIndex = config.playlists[ playlist ].indexOf( parseInt( config.active_index ) );\n\n\t\t\t\t/*\n\t\t\t\t\tChecks to see if the next index is still less than the length of the playlist.\n\t\t\t\t\tIf it is, use the next index othwerwise get the first song in the playlist.\n\t\t\t\t*/\n\t\t\t\tif( playlistActiveSongIndex + 1 < config.playlists[ playlist ].length ){\n\t\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][ playlistActiveSongIndex + 1 ] );\n\t\t\t\t}else{\n\t\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][0] );\n\t\t\t\t\tendOfList = true;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t\tSets the next inex to the active index in the config.\n\t\t\t\t*/\n\t\t\t\tnextIndex = config.active_index;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song playing.\n\t\t*/\n\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChanges the song to the next song in the playlist.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( nextIndex );\n\n\t\t/*\n\t\t\tIf it's the end of the song in the playlist, and repeat for\n\t\t\tthe playlist is not on, do nothing.\n\t\t*/\n\t\tif( endOfList && !config.repeat_statuses[playlist] ){\n\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the song has ended and repeat is on, play the song.\n\t\t\t*/\n\t if( !( songEnded && !config.repeat_statuses[playlist] && endOfList ) ){\n\t\t\t\tAmplitudeCore.play();\n\t\t\t}\n\t\t}\n\n\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\n\n /*\n \tSyncs the main play pause button, playlist play pause button and\n \tsong play pause.\n */\n\t\tAmplitudeVisualSync.syncMainPlayPause( );\n\t\tAmplitudeVisualSync.syncPlaylistPlayPause(playlist);\n\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, nextIndex);\n\n /*\n \tCall after next callback\n */\n AmplitudeCoreHelpers.runCallback('after_next');\n\n\t\t/*\n\t\t\tIf we are repeating the song, call the song repeated callback\n\t\t*/\n\t\tif( config.repeat_song ){\n\t\t\tAmplitudeCoreHelpers.runCallback('song_repeated');\n\t\t}\n\t}\n\n\t/**\n\t * Sets the previous song\n\t * @access public\n\t *\n\t/*--------------------------------------------------------------------------\n\t\tSets the previous song\n\t--------------------------------------------------------------------------*/\n\tfunction setPrev(){\n\t\t/*\n\t\t\tInitializes the prev index variable. This will be the\n\t\t\tindex of the song that is next.\n\t\t*/\n\t\tlet prevIndex = 0;\n\n\t\t/*\n\t\t\tIf the shuffle is on for the individual songs, we get the previous\n\t\t\tsong.\n\t\t*/\n\t\tif( config.shuffle_on ){\n\t\t\t/*\n\t\t\t\tIf the previous index is greater than or equal to 0, we use the active\n\t\t\t\tindex - 1.\n\t\t\t*/\n\t\t\tif( parseInt( config.shuffle_active_index ) - 1 >= 0 ){\n\t\t\t\t/*\n\t\t\t\t\tSets the new active to be 1 less than the current active index.\n\t\t\t\t*/\n\t\t\t\tconfig.shuffle_active_index = parseInt( config.shuffle_active_index ) - 1;\n\n\t\t\t\t/*\n\t\t\t\t\tGets the index of the song in the song array for the new index.\n\t\t\t\t*/\n\t\t\t\tprevIndex = config.shuffle_list[ parseInt( config.shuffle_active_index ) ].original_index;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the active index and previous index.\n\t\t\t\t*/\n\t\t\t\tconfig.shuffle_active_index = config.shuffle_list.length - 1;\n\t\t\t\tprevIndex = config.shuffle_list[ parseInt( config.shuffle_list.length ) - 1 ].original_index;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tIf the active index - 1 is greater than or equal to 0, we subtract 1 from the\n\t\t\t\tactive index otherwise we set the active index to the end of the songs array index.\n\t\t\t*/\n\t\t\tif( parseInt( config.active_index ) - 1 >= 0 ){\n\t\t\t\tconfig.active_index = parseInt( config.active_index ) - 1;\n\t\t\t}else{\n\t\t\t\tconfig.active_index = config.songs.length - 1;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSet the previous index.\n\t\t\t*/\n\t\t\tprevIndex = config.active_index;\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChange the song to the index we need.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( prevIndex );\n\n\t\t/*\n\t\t\tPlay the next song.\n\t\t*/\n\t\tAmplitudeCore.play();\n\n\t\t/*\n\t\t\tSync the play/pause buttons to the current state of the player.\n\t\t*/\n\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\tAmplitudeVisualSync.syncSongPlayPause( null, prevIndex, 'playing' );\n\n\t\t/*\n\t\t\tCall after prev callback\n\t\t*/\n\t\tAmplitudeCoreHelpers.runCallback('after_prev');\n\t}\n\n\t/**\n\t * Sets the previous song in a playlist\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist we are setting the previous for.\n\t */\n\tfunction setPrevPlaylist( playlist ){\n\t\t/*\n\t\t\tInitializes the prev index variable. This will be the\n\t\t\tindex of the song that is next.\n\t\t*/\n\t\tlet prevIndex = 0;\n\n\t\t/*\n\t\t\tIf the shuffle is on for the playlist, we get the previous\n\t\t\tsong.\n\t\t*/\n\t\tif( config.shuffled_statuses[ playlist ] ){\n\t\t\t/*\n\t\t\t\tGets the active song index for the shuffled playlist\n\t\t\t*/\n\t\t\tlet shuffledPlaylistActiveSongIndex = parseInt( config.shuffled_active_indexes[ playlist ] );\n\n\t\t\t/*\n\t\t\t\tIf the shuffled song active index is greater than or equal to 0,\n\t\t\t\twe use the active index - 1.\n\t\t\t*/\n\t\t\tif( shuffledPlaylistActiveSongIndex - 1 >= 0 ){\n\t\t\t\t/*\n\t\t\t\t\tSets the active index to the active song index - 1\n\t\t\t\t*/\n\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = shuffledPlaylistActiveSongIndex - 1;\n\n\t\t\t\t/*\n\t\t\t\t\tGets the index of the song in the song array for the new index.\n\t\t\t\t*/\n\t\t\t\tprevIndex = config.shuffled_playlists[ playlist ][ config.shuffled_active_indexes[ playlist ] ].original_index;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the active index and previous index.\n\t\t\t\t*/\n\t\t\t\tconfig.shuffled_active_indexes[ playlist ] = config.shuffled_playlists[ playlist ].length - 1;\n\t\t\t\tprevIndex = config.shuffled_playlists[ playlist ][ config.shuffled_playlists[ playlist ].length - 1 ].original_index;\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tGets the active song index for the playlist\n\t\t\t*/\n\t\t\tlet playlistActiveSongIndex = config.playlists[ playlist ].indexOf( parseInt( config.active_index ) );\n\n\t\t\t/*\n\t\t\t\tIf the active song index in the playlist - 1 is greater than\n\t\t\t\tor equal to 0, then we use the active song index - 1.\n\t\t\t*/\n\t\t\tif( playlistActiveSongIndex - 1 >= 0 ){\n\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][ playlistActiveSongIndex - 1 ] );\n\t\t\t}else{\n\t\t\t\tconfig.active_index = parseInt( config.playlists[ playlist ][ config.playlists[ playlist ].length - 1 ] );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSet the previous index to the active index for use later.\n\t\t\t*/\n\t\t\tprevIndex = config.active_index;\n\t\t}\n\n\t\t/*\n\t\t\tStops the active song.\n\t\t*/\n\t\tAmplitudeCore.stop();\n\n\t\t/*\n\t\t\tChanges the song to the prev song in the playlist.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( prevIndex );\n\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\n\t\t/*\n\t\t\tPlays the song\n\t\t*/\n\t\tAmplitudeCore.play();\n\n\t\t/*\n\t\t\tSyncs the main play pause button, playlist play pause button and\n\t\t\tsong play pause.\n\t\t*/\n\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\tAmplitudeVisualSync.syncPlaylistPlayPause( playlist, 'playing' );\n\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, prevIndex, 'playing' );\n\n\t\t/*\n\t\t\tCall after prev callback\n\t\t*/\n\t\tAmplitudeCoreHelpers.runCallback('after_prev');\n\t}\n\n\t/**\n\t * Runs an event on key down\n\t *\n\t * @access public\n\t * @param {number} key \t- The key code the event is bound to.\n\t */\n\tfunction runKeyEvent( key ){\n\t\t/*\n\t\t\tChecks to see if the user bound an event to the code pressed.\n\t\t*/\n\t\tif( config.bindings[key] != undefined ){\n\t\t\t/*\n\t\t\t\tDetermine which event should be run if bound.\n\t\t\t*/\n\t\t\tswitch( config.bindings[key] ){\n\t\t\t\t/*\n\t\t\t\t\tFires a play pause event.\n\t\t\t\t*/\n\t\t\t\tcase 'play_pause':\n\t\t\t\t\tsetSongPlayPause( config.active_playlist, config.active_index );\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a next event.\n\t\t\t\t*/\n\t\t\t\tcase 'next':\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the current state of the player\n\t\t\t\t\t\tis in playlist mode or not playlist mode.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\t\tsetNext();\n\t\t\t\t\t}else{\n\t\t\t\t\t\tsetNextPlaylist( config.active_playlist );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a previous event.\n\t\t\t\t*/\n\t\t\t\tcase 'prev':\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the current playlist has been set\n\t\t\t\t\t\tor null and set the previous song.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\t\tAmplitudeEventsHelpers.setPrev();\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( config.active_playlist );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a stop event.\n\t\t\t\t*/\n\t\t\t\tcase 'stop':\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets all of the play/pause buttons to pause\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tStops the active song.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeCore.stop();\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a shuffle event.\n\t\t\t\t*/\n\t\t\t\tcase 'shuffle':\n\t\t\t\t\t/*\n\t\t\t\t\t\tCheck to see if the current playlist has been set\n\t\t\t\t\t\tor null and set the previous song.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\t\tAmplitudesEventHelpers.setShuffle( null );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeEvenstHelpers.setShuffle( config.active_playlist );\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t\t/*\n\t\t\t\t\tFires a repeat event.\n\t\t\t\t*/\n\t\t\t\tcase 'repeat':\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets repeat to the opposite of what it was set to\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat );\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tVisually sync repeat\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncRepeat();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t\tReturn the publically scoped functions\n\t*/\n\treturn {\n\t\tcomputeCurrentTimes: computeCurrentTimes,\n\t\tcomputeSongDuration: computeSongDuration,\n\t\tcomputeSongCompletionPercentage: computeSongCompletionPercentage,\n\t\tsetPlaybackSpeed: setPlaybackSpeed,\n\t\tsetRepeat: setRepeat,\n\t\tsetRepeatSong: setRepeatSong,\n\t\tsetMainPlayPause: setMainPlayPause,\n\t\tsetPlaylistPlayPause: setPlaylistPlayPause,\n\t\tsetSongPlayPause: setSongPlayPause,\n\t\tsetShuffle: setShuffle,\n\t\tsetNext: setNext,\n\t\tsetNextPlaylist: setNextPlaylist,\n\t\tsetPrev: setPrev,\n\t\tsetPrevPlaylist: setPrevPlaylist,\n\t\trunKeyEvent: runKeyEvent\n\t}\n})();\n\nexport default AmplitudeEventsHelpers\n\n\n\n// WEBPACK FOOTER //\n// ./src/events/helpers.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * AmplitudeJS Core Module\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * AmplitudeJS Core Helpers\n * @module core/AmplitudeHelpers\n */\nimport AmplitudeHelpers from '../core/helpers.js';\n\n/**\n * AmplitudeJS Events\n * @module events/AmplitudeEvents\n */\nimport AmplitudeEvents from '../events/events.js';\n\n/**\n * AmplitudeJS Soundcloud\n * @module soundcloud/AmplitudeSoundcloud\n */\nimport AmplitudeSoundcloud from '../soundcloud/soundcloud.js';\n\n/**\n * AmplitudeJS Visual Sync\n * @module visual/AmplitudeVisualSync\n*/\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * AmplitudeJS Initializer Module. Helps with the handling of all of the\n * initialization for AmplitudeJS.\n *\n * @module init/AmplitudeInitializer\n */\nlet AmplitudeInitializer = (function () {\n\n\t/**\n * The main init function. The user will call this through\n\t * Amplitude.init({}) and pass in their settings.\n\t *\n\t * Public Accessor: Amplitude.init( user_config_json )\n\t * @access public\n * @param {object} userConfig - A JSON object of user defined values that help configure and initialize AmplitudeJS.\n */\n\tfunction initialize( userConfig ){\n\t\tlet ready = false;\n\n\t\t/*\n\t\t\tReset the config on init so we have a clean slate. This is if the\n\t\t\tuser has to re-init.\n\t\t*/\n\t\tAmplitudeHelpers.resetConfig();\n\n\t\t/*\n\t\t\tInitialize event handlers on init. This will clear any old\n\t\t\tevent handlers on the amplitude element and re-bind what is\n\t\t\tnecessary.\n\t\t*/\n\t\tAmplitudeEvents.initializeEvents();\n\n\t\t/*\n\t\t\tInitializes debugging right away so we can use it for the rest\n\t\t\tof the configuration.\n\t\t*/\n\t\tconfig.debug = ( userConfig.debug != undefined ? userConfig.debug : false );\n\n\t\t/*\n\t\t\tChecks to see if the user has songs defined.\n\t\t*/\n\t\tif( userConfig.songs ){\n\t\t\t/*\n\t\t\t\tChecks to see if the user has some songs in the songs array.\n\t\t\t*/\n\t\t\tif( userConfig.songs.length != 0 ){\n\t\t\t\t/*\n\t\t\t\t\tCopies over the user defined songs. and prepares\n\t\t\t\t\tAmplitude for the rest of the configuration.\n\t\t\t\t*/\n\t\t\t\tconfig.songs = userConfig.songs;\n\t\t\t\t/*\n\t\t\t\t\tFlag amplitude as ready.\n\t\t\t\t*/\n\t\t\t\tready = true;\n\t\t\t}else{\n\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'Please add some songs, to your songs object!' );\n\t\t\t}\n\t\t}else{\n\t\t\tAmplitudeHelpers.writeDebugMessage( 'Please provide a songs object for AmplitudeJS to run!' );\n\t\t}\n\n\t\t/**\n\t\t * Initializes the audio context. In this method it checks to see if the\n\t\t * user wants to use visualizations or not before proceeding.\n\t\t * @todo MAKE HANDLED BY AMPLITUDE FX.\n\t\t */\n\t\t//privateHelpInitializeAudioContext();\n\n\t\t/*\n\t\t\tChecks if the user has any playlists defined. If they do\n\t\t\twe have to initialize the functionality for the playlists.\n\t\t*/\n\t\tif( userConfig.playlists && countPlaylists( userConfig.playlists ) > 0 ){\n\t\t\t/*\n\t\t\t\tCopy the playlists over to Amplitude\n\t\t\t*/\n\t\t\tconfig.playlists = userConfig.playlists;\n\n\t\t\t/*\n\t\t\t\tInitialize default live settings\n\t\t\t*/\n\t\t\tinitializeDefaultLiveSettings();\n\n\t\t\t/*\n\t\t\t\tCheck to see if the user has valid song indexes in their playlist.\n\t\t\t*/\n\t\t\tcheckValidSongsInPlaylists();\n\n\t\t\t/*\n\t\t\t\tInitialize the shuffle status of the playlists.\n\t\t\t*/\n\t\t\tinitializePlaylistShuffleStatuses();\n\n\t\t\t/*\n\t\t\t\tInitialize the repeat status for the playlits.\n\t\t\t*/\n\t\t\tinitializePlaylistsRepeatStatuses();\n\n\t\t\t/*\n\t\t\t\tInitialize temporary place holders for shuffle lists.\n\t\t\t*/\n\t\t\tinitializePlaylistShuffleLists();\n\n\t\t\t/*\n\t\t\t\tInitializes the active shuffled indexes for shuffled playlists.\n\t\t\t*/\n\t\t\tinitializePlaylistShuffleIndexes();\n\n\t\t\t/*\n\t\t\t\tInitializes the first song in the playlist\n\t\t\t*/\n\t\t\tinitializeFirstSongInPlaylistMetaData();\n\t\t}\n\n\t\t/*\n\t\t\tWhen the preliminary config is ready, we are ready to proceed.\n\t\t*/\n\t\tif( ready ){\n\t\t\t/*\n\t\t\t\tCopies over the soundcloud information to the global config\n\t\t\t\twhich will determine where we go from there.\n\t\t\t*/\n\t\t\tconfig.soundcloud_client = ( userConfig.soundcloud_client != undefined ? userConfig.soundcloud_client : '' );\n\n\t\t\t/*\n\t\t\t\tChecks if we want to use the art loaded from soundcloud.\n\t\t\t*/\n\t\t\tconfig.soundcloud_use_art = ( userConfig.soundcloud_use_art != undefined ? userConfig.soundcloud_use_art : '' );\n\n\t\t\t/*\n\t\t\t\tIf the user provides a soundcloud client then we assume that\n\t\t\t\tthere are URLs in their songs that will reference SoundcCloud.\n\t\t\t\tWe then copy over the user config they provided to the\n\t\t\t\ttemp_user_config so we don't mess up the global or their configs\n\t\t\t\tand load the soundcloud information.\n\t\t\t*/\n\t\t\tlet tempUserConfig = {};\n\n\t\t\tif( config.soundcloud_client != '' ){\n\t\t\t\ttempUserConfig = userConfig;\n\n\t\t\t\t/*\n\t\t\t\t\tLoad up SoundCloud for use with AmplitudeJS.\n\t\t\t\t*/\n\t\t\t\tAmplitudeSoundcloud.loadSoundCloud( tempUserConfig );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tThe user is not using Soundcloud with Amplitude at this point\n\t\t\t\t\tso we just finish the configuration with the users's preferences.\n\t\t\t\t*/\n\t\t\t\tsetConfig( userConfig );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDebug out what was initialized with AmplitudeJS.\n\t\t*/\n\t\tAmplitudeHelpers.writeDebugMessage( 'Initialized With: ');\n\t\tAmplitudeHelpers.writeDebugMessage( config );\n\t}\n\n\t/**\n\t * Rebinds all of the elements in the display.\n\t *\n\t * Public Accessor: Amplitude.rebindDisplay()\n\t * @access public\n\t */\n\tfunction rebindDisplay(){\n\t\tAmplitudeEvents.initializeEvents();\n\t\tAmplitudeVisualSync.displaySongMetadata();\n\t}\n\n\t/**\n\t * Finishes the initalization of the config. Takes all of the user defined\n\t * parameters and makes sure they override the defaults. The important\n\t * config information is assigned in the publicInit() function.\n\t *\n\t * This function can be called from 2 different locations:\n\t * \t1. Right away on init after the important settings are defined.\n\t *\n\t * \t2. After all of the Soundcloud URLs are resolved properly and\n\t *\t \tsoundcloud is configured. We will need the proper URLs from Soundcloud\n\t * \t\tto stream through Amplitude so we get those right away before we\n\t * \t\tset the information and the active song\n\t *\n\t * @access public\n\t * @param {object} userConfig - A JSON object of user defined values that help configure and initialize AmplitudeJS.\n\t */\n\tfunction setConfig( userConfig ){\n\t\t/*\n\t\t\tCheck to see if the user entered a start song\n\t\t*/\n\t\tif( userConfig.start_song != undefined ){\n\t\t\t/*\n\t\t\t\tEnsure what has been entered is an integer.\n\t\t\t*/\n\t\t\tif( AmplitudeHelpers.isInt( userConfig.start_song ) ){\n\t\t\t\tAmplitudeHelpers.changeSong( userConfig.start_song );\n\t\t\t}else{\n\t\t\t\tAmplitudeHelpers.writeDebugMessage(\"You must enter an integer index for the start song.\");\n\t\t\t}\n\t\t}else{\n\t\t\tAmplitudeHelpers.changeSong( 0 );\n\t\t}\n\n\t\t/*\n\t\t\tInitialize a sh\n\t\t*/\n\t\tif( userConfig.shuffle_on != undefined && userConfig.shuffle_on ){\n\t\t\tconfig.shuffle_on = true;\n\t\t\tAmplitudeHelpers.shuffleSongs();\n\n\t\t\t/*\n\t\t\t\tVisually sync the shuffle statuses\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncShuffle( config.shuffle_on );\n\n\t\t\tAmplitudeHelpers.changeSong( config.shuffle_list[0].original_index );\n\t\t}\n\n\t\t/*\n\t\t\tAllows the user to set whether they want to continue to the next song\n\t\t\twhen the current song finishes or not. In any scenario that's not a playlist,\n\t\t\tcontining to the next song may not be desired.\n\t\t*/\n\t\tconfig.continue_next = ( userConfig.continue_next != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t userConfig.continue_next :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t true );\n\n\t\t/*\n\t\t\tIf the user defined a playback speed, we copy over their\n\t\t\tpreference here, otherwise we default to normal playback\n\t\t\tspeed of 1.0.\n\t\t*/\n\t\tconfig.playback_speed = ( userConfig.playback_speed != undefined ?\n\t\t\t\t\t\t\t\t \t\t\t\t\t\tuserConfig.playback_speed :\n\t\t\t\t\t\t\t\t \t\t\t\t\t\t1.0 );\n\n\t\t/*\n\t\t\tSets the audio playback speed.\n\t\t*/\n\t\tAmplitudeCore.setPlaybackSpeed( config.playback_speed );\n\n\t\t/*\n\t\t\tIf the user wants the song to be pre-loaded for instant\n\t\t\tplayback, they set it to true. By default it's set to just\n\t\t\tload the metadata.\n\t\t*/\n\t\tconfig.active_song.preload = ( userConfig.preload != undefined ?\n\t\t\t\t\t\t\t\t\t \t\t\t\t\t\t\t userConfig.preload :\n\t\t\t\t\t\t\t\t\t \t\t\t\t\t \t\t \"auto\" );\n\n\t\t/*\n\t\t\tInitializes the user defined callbacks. This should be a JSON\n\t\t\tobject that contains a key->value store of the callback name\n\t\t\tand the name of the function the user needs to call.\n\t\t*/\n\t\tconfig.callbacks = ( userConfig.callbacks != undefined ?\n\t\t\t\t\t\t\t \t\t\t\t\t userConfig.callbacks :\n\t\t\t\t\t\t\t \t\t\t\t \t {} );\n\n\t\t/*\n\t\t\tInitializes the user defined key bindings. This should be a JSON\n\t\t\tobject that contains a key->value store of the key event number\n\t\t\tpressed and the method to be run.\n\t\t*/\n\t\tconfig.bindings = ( userConfig.bindings != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\tuserConfig.bindings :\n\t\t\t\t\t\t\t\t\t\t\t\t{} );\n\n\t\t/*\n\t\t\tThe user can define a starting volume in a range of 0-100 with\n\t\t\t0 being muted and 100 being the loudest. After the config is set\n\t\t\tAmplitude sets the active song's volume to the volume defined\n\t\t\tby the user.\n\t\t*/\n\t\tconfig.volume = ( userConfig.volume != undefined ?\n\t\t\t \t\t\t \t\t\t\tuserConfig.volume :\n\t\t\t \t\t\t \t\t\t\t50 );\n\n\t\t/*\n\t\t\tThe user can set the volume increment and decrement values between 1 and 100\n\t\t\tfor when the volume up or down button is pressed. The default is an increase\n\t\t\tor decrease of 5.\n\t\t*/\n\t\tconfig.volume_increment = ( userConfig.volume_increment != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuserConfig.volume_increment :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t5 );\n\n\t\tconfig.volume_decrement = ( userConfig.volume_decrement != undefined ?\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuserConfig.volume_decrement :\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t5 );\n\n\t\t/*\n\t\t\tSet the volume to what is defined in the config. The user can define this,\n\t\t\tso we should set it up that way.\n\t\t*/\n\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t/*\n\t\t\tSince the user can define a start volume, we want our volume\n\t\t\tsliders to sync with the user defined start value.\n\t\t*/\n\t\tAmplitudeVisualSync.syncVolumeSliders();\n\n\t\t/*\n\t\t\tIf the user defines default album art, this image will display if the active\n\t\t\tsong doesn't have album art defined.\n\t\t*/\n\t\tif( userConfig.default_album_art != undefined ){\n\t\t\tconfig.default_album_art = userConfig.default_album_art;\n\t\t}else{\n\t\t\tconfig.default_album_art = '';\n\t\t}\n\n\t\t/*\n\t\t\tSyncs all of the visual time elements to 00.\n\t\t*/\n\t\tAmplitudeVisualSync.resetTimes();\n\n\t\t/*\n\t\t\tSets all of the play pause buttons to pause.\n\t\t*/\n\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t/*\n\t\t\tSets the meta data for the songs automatically.\n\t\t*/\n\t\tAmplitudeVisualSync.syncSongsMetaData();\n\n\t\t/*\n\t\t\tIf the user has autoplay enabled, then begin playing the song. Everything should\n\t\t\tbe configured for this to be ready to play.\n\t\t*/\n\t\tif( userConfig.autoplay ){\n\t\t\t/*\n\t\t\t\tIf the user hasn't set a starting playlist, set it to null otherwise initialize to the\n\t\t\t\tstarting playlist selected by the user.\n\t\t\t*/\n\t\t\tif( userConfig.starting_playlist == '' ){\n\t\t\t\tconfig.active_playlist = null;\n\t\t\t}else{\n\t\t\t\tconfig.active_playlist = userConfig.starting_playlist;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSync the main and song play pause buttons.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, 0, 'playing' );\n\n\t\t\t/*\n\t\t\t\tStart playing the song\n\t\t\t*/\n\t\t\tAmplitudeCore.play();\n\t\t}\n\n\t\t/*\n\t\t\tIf the user has selected a starting playlist, we need to set the starting playlist\n\t\t\tand sync the visuals\n\t\t*/\n\t\tif( userConfig.starting_playlist != undefined && userConfig.starting_playlist != '' ){\n\t\t\t/*\n\t\t\t\tSet the active playlist to the starting playlist by the user\n\t\t\t*/\n\t\t\tconfig.active_playlist = userConfig.starting_playlist;\n\n\t\t\t/*\n\t\t\t\tCheck if the user defined a song to start with in the playlist.\n\t\t\t*/\n\t\t\tif( userConfig.starting_playlist_song != undefined && userConfig.starting_playlist_song != '' ){\n\t\t\t\t/*\n\t\t\t\t\tEnsure the song is a valid index.\n\t\t\t\t*/\n\t\t\t\tif( typeof userConfig.playlists[ userConfig.starting_playlist ][ parseInt( userConfig.starting_playlist_song ) ] != undefined ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the player to the song defined by the user.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeHelpers.changeSong( userConfig.playlists[ userConfig.starting_playlist ][ parseInt( userConfig.starting_playlist_song ) ] );\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tSet the player to the first song in the playlist\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeHelpers.changeSong( userConfig.playlists[ userConfig.starting_playlist ][0] );\n\t\t\t\t\t/*\n\t\t\t\t\t\tDebug that the song index doesn't exist\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeHelpers.writeDebugMessage( 'The index of '+userConfig.starting_playlist_song+' does not exist in the playlist '+userConfig.starting_playlist );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the player to the first song in the playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeHelpers.changeSong( userConfig.playlists[ userConfig.starting_playlist ][0] );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tSync the main and song play pause buttons.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, 0, 'paused' );\n\t\t}\n\n\t\t/*\n\t\t\tRun after init callback\n\t\t*/\n\t\tAmplitudeHelpers.runCallback('after_init');\n\t}\n\n\t/**\n\t * Counts the number of playlists the user has configured. This ensures\n\t * that the user has at least 1 playlist so we can validate the songs\n\t * defined in the playlist are correct and they didn't enter an invalid\n\t * ID.\n\t *\n\t * @access private\n\t * @param {object} playlists \t-\n\t */\n\tfunction countPlaylists( playlists ){\n\t\t/*\n\t\t\tInitialize the placeholders to iterate through the playlists\n\t\t\tand find out how many we have to account for.\n\t\t*/\n\t\tlet size = 0, key;\n\n\t\t/*\n\t\t\tIterate over playlists and if the user has the playlist defined,\n\t\t\tincrement the size of playlists.\n\t\t*/\n\t\tfor ( key in playlists ) {\n\t\t\tif( playlists.hasOwnProperty( key) ){\n\t\t\t\tsize++;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tDebug how many playlists are in the config.\n\t\t*/\n\t\tAmplitudeHelpers.writeDebugMessage( 'You have '+size+' playlist(s) in your config' );\n\n\t\t/*\n\t\t\tReturn the number of playlists in the config.\n\t\t*/\n\t\treturn size;\n\t}\n\n\t/**\n\t* Ensures the indexes in the playlists are valid indexes. The song has\n\t* to exist in the Amplitude config to be played correctly.\n\t*\n\t* @access private\n\t*/\n\tfunction checkValidSongsInPlaylists(){\n\t\t/*\n\t\t\tIterate over all of the config's playlists\n\t\t*/\n\t\tfor( let key in config.playlists ){\n\t\t\t/*\n\t\t\t\tChecks if the playlist key is accurate.\n\t\t\t*/\n\t\t\tif( config.playlists.hasOwnProperty( key) ){\n\t\t\t\t/*\n\t\t\t\t\tChecks if the playlist has songs.\n\t\t\t\t*/\n\t\t\t\tif( config.playlists[key].songs ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tIterate over all of the songs in the playlist\n\t\t\t\t\t*/\n\t\t\t\t\tfor( let i = 0; i < config.playlists[key].songs.length; i++ ){\n\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tCheck to see if the index for the song in the playlist\n\t\t\t\t\t\t\texists in the songs config.\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tif( !config.songs[ config.playlists[key].songs[i] ] ){\n\t\t\t\t\t\t\tAmplitudeHelpers.writeDebugMessage('The song index: '+config.playlists[key].songs[i]+' in playlist with key: '+key+' is not defined in your songs array!');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Initializes the shuffle statuses for each of the playlists. These will\n\t * be referenced when we shuffle individual playlists.\n\t *\n\t * @access private\n\t */\n\tfunction initializePlaylistShuffleStatuses(){\n\t\t/*\n\t\t\tIterate over all of the playlists the user defined adding\n\t\t\tthe playlist key to the shuffled playlist array and creating\n\t\t\tand empty object to house the statuses.\n\t\t*/\n\t\tfor ( let key in config.playlists ) {\n\t\t\tconfig.shuffled_statuses[ key ] = false;\n\t\t}\n\t}\n\n\t/**\n\t * Initializes the repeat statuses for each of the playlists. These will\n\t * be referenced when we repeat individual playlits.\n\t *\n\t * @access private\n\t */\n\t function initializePlaylistsRepeatStatuses(){\n\t\t /*\n \t\t\tIterate over all of the playlists the user defined adding\n \t\t\tthe playlist key to the repeated playlist array and creating\n \t\t\tand empty object to house the statuses.\n \t\t*/\n \t\tfor ( let key in config.playlists ) {\n \t\t\tconfig.repeat_statuses[ key ] = false;\n \t\t}\n\t }\n\n\t/**\n\t * Initializes the shuffled playlist placeholders. These will be set for\n\t * playlists that are shuffled and contain the shuffled songs.\n\t *\n\t * @access private\n \t */\n\tfunction initializePlaylistShuffleLists(){\n\t\t/*\n\t\t\tIterate over all of the playlists the user defined adding\n\t\t\tthe playlist key to the shuffled playlists array and creating\n\t\t\tand empty object to house the shuffled playlists\n\t\t*/\n\t\tfor ( let key in config.playlists ) {\n\t\t\tconfig.shuffled_playlists[ key ] = [];\n\t\t}\n\t}\n\n\t/**\n\t * Initializes the shuffled playlist indexes array. These will be set for\n\t * playlists that are shuffled and contain the active shuffled index.\n\t *\n\t * @access private\n\t */\n\tfunction initializePlaylistShuffleIndexes(){\n\t\t/*\n\t\t\tIterates over all of the playlists adding a key\n\t\t\tto the shuffled_active_indexes array that contains\n\t\t\tthe active shuffled index.\n\t\t*/\n\t\tfor( let key in config.playlists ) {\n\t\t\tconfig.shuffled_active_indexes[ key ] = 0;\n\t\t}\n\t}\n\n\t/**\n\t * Intializes the display for the first song in the playlist meta data.\n\t *\n\t * @access private\n\t */\n\tfunction initializeFirstSongInPlaylistMetaData(){\n\t\t/*\n\t\t\tIterates over all of the playlists setting the meta data for the\n\t\t\tfirst song.\n\t\t*/\n\t\tfor( let key in config.playlists ){\n\t\t\tAmplitudeVisualSync.setFirstSongInPlaylist( config.songs[ config.playlists[ key ][0] ] , key );\n\t\t}\n\t}\n\n\t/**\n\t * Intializes the default live settings for all of the songs.\n\t *\n\t * @access priavet\n\t */\n\tfunction initializeDefaultLiveSettings(){\n\t\tfor( let i = 0; i < config.songs.length; i++ ){\n\t\t\tif( config.songs[i].live == undefined ){\n\t\t\t\tconfig.songs[i].live = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t\tReturns the publicly accessible methods\n\t*/\n\treturn {\n\t\tinitialize: initialize,\n\t\tsetConfig: setConfig,\n\t\trebindDisplay: rebindDisplay\n\t}\n})();\n\nexport default AmplitudeInitializer\n\n\n\n// WEBPACK FOOTER //\n// ./src/init/init.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the helpers for the event handlers.\n * @module events/AmplitudeEventsHelpers\n */\nimport AmplitudeEventsHelpers from './helpers.js';\n\n/**\n * Imports the visual sync module to keep the display in sync with AmplitudeJS\n * @module visual/AmplitudeVisualSync\n */\nimport AmplitudeVisualSync from '../visual/visual.js';\n\n/**\n * Imports the core module of Amplitude which handles the basic functions\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from '../core/core.js';\n\n/**\n * Imports the core helpers for Amplitude which help run some of AmplitudeJS functions\n * @module core/AmplitudeHelpers\n */\nimport AmplitudeCoreHelpers from '../core/helpers.js';\n\n/**\n * These functions handle the events that we bound to each element and\n * prepare for a function to be called. These kind of act like filters/middleware.\n *\n * @module events/AmplitudeHandlers\n */\nexport default {\n\t/**\n\t * When the time updates on the active song, we sync the current time displays\n\t *\n\t * HANDLER FOR: timeupdate\n\t *\n\t * @access public\n\t */\n\tupdateTime: function(){\n\t\t/*\n\t\t\tHelp from: http://jsbin.com/badimipi/1/edit?html,js,output\n\t\t*/\n\t\tif( config.active_song.buffered.length - 1 >= 0 ){\n\t\t\tlet bufferedEnd = config.active_song.buffered.end( config.active_song.buffered.length - 1 );\n\t\t\tlet duration = config.active_song.duration;\n\n\t\t\tconfig.buffered = ( ( bufferedEnd / duration ) * 100 );\n\t\t}\n\n\t\t/*\n\t\t\tSync the buffered progress bars.\n\t\t*/\n\t\tAmplitudeVisualSync.syncBufferedProgressBars();\n\n\t\t/*\n\t\t\tIf the current song is not live, then\n\t\t\twe can update the time information. Otherwise the\n\t\t\tcurrent time updates wouldn't mean much since the time\n\t\t\tis infinite.\n\t\t*/\n\t\tif( !config.active_metadata.live ){\n\t\t\t/*\n\t\t\t\tCompute the current time\n\t\t\t*/\n\t\t\tlet currentTime = AmplitudeEventsHelpers.computeCurrentTimes();\n\n\t\t\t/*\n\t\t\t\tCompute the song completion percentage\n\t\t\t*/\n\t\t\tlet songCompletionPercentage = AmplitudeEventsHelpers.computeSongCompletionPercentage();\n\n\t\t\t/*\n\t\t\t\tComputes the song duration\n\t\t\t*/\n\t\t\tlet songDuration = AmplitudeEventsHelpers.computeSongDuration();\n\n\t\t\t/*\n\t\t\t\tSync the current time elements with the current\n\t\t\t\tlocation of the song and the song duration elements with\n\t\t\t\tthe duration of the song.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncCurrentTime( currentTime, songCompletionPercentage );\n\t\t\tAmplitudeVisualSync.syncSongDuration( currentTime, songDuration );\n\n\t\t\t/*\n\t\t\t\tRuns the callback defined for the time update.\n\t\t\t*/\n\t\t\tAmplitudeCoreHelpers.runCallback( 'time_update' );\n\t\t}\n\t},\n\n\t/**\n\t * When the keydown event is fired, we determine which function should be run\n\t * based on what was passed in.\n\t *\n\t * HANDLER FOR: keydown\n\t *\n\t * @access public\n\t */\n\tkeydown: function( event ){\n\t\tAmplitudeEventsHelpers.runKeyEvent( event.which );\n\t},\n\n\t/**\n\t * When the song has ended, handles what to do next\n\t *\n\t * HANDLER FOR: ended\n\t *\n\t * @access public\n\t */\n\tsongEnded: function(){\n\t\tif( config.continue_next ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is not set, we set the\n\t\t\t\tnext song that's in the songs array.\n\t\t\t*/\n\t\t\tif( config.active_playlist == ''\n\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\tAmplitudeEventsHelpers.setNext( true );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tSet the next song in the playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( config.active_playlist, true );\n\t\t\t}\n\t\t}else{\n\t\t\tif( !config.is_touch_moving ){\n\t\t\t\t/*\n\t\t\t\t\tSets all of the play/pause buttons to pause\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t\t\t/*\n\t\t\t\t\tStops the active song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCore.stop();\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * As the song is buffered, we can display the buffered percentage in\n\t * a progress bar.\n\t *\n\t * HANDLER FOR: ended\n\t *\n\t * @access public\n\t */\n\tprogress: function(){\n\t\t/*\n\t\t\tHelp from: http://jsbin.com/badimipi/1/edit?html,js,output\n\t\t*/\n\t\tif( config.active_song.buffered.length - 1 >= 0 ){\n\t\t\tlet bufferedEnd = config.active_song.buffered.end( config.active_song.buffered.length - 1 );\n\t\t\tlet duration = config.active_song.duration;\n\n\t\t\tconfig.buffered = ( ( bufferedEnd / duration ) * 100 );\n\t\t}\n\n\t\t/*\n\t\t\tSync the buffered progress bars.\n\t\t*/\n\t\tAmplitudeVisualSync.syncBufferedProgressBars();\n\t},\n\n\t/**\n\t * Handles an event on a play button in Amplitude.\n\t *\n\t * HANDLER FOR: 'amplitude-play'\n\t *\n\t * @access public\n\t * @TODO Finish commenting and re-structure\n\t */\n\tplay: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tGets the attribute for song index so we can check if\n\t\t\t\tthere is a need to change the song. In some scenarios\n\t\t\t\tthere might be multiple play classes on the page. In that\n\t\t\t\tcase it is possible the user could click a different play\n\t\t\t\tclass and change the song.\n\t\t\t*/\n\t\t\tlet playButtonSongIndex = this.getAttribute('amplitude-song-index');\n\t\t\tlet playButtonPlaylistIndex = this.getAttribute('amplitude-playlist');\n\n\t\t\tif( playButtonPlaylistIndex == null && playButtonSongIndex == null ){\n\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( config.active_playlist, config.active_index );\n\t\t\t}\n\n\t\t\t/*\n\n\t\t\t*/\n\t\t\tif( playButtonPlaylistIndex != null && playButtonPlaylistIndex != '' ){\n\t\t\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playButtonPlaylistIndex ) ){\n\t\t\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playButtonPlaylistIndex );\n\n\t\t\t\t\tif( playButtonSongIndex != null ){\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( playButtonSongIndex );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( config.playlists[ playButtonPlaylistIndex ][0] );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\tif( playButtonSongIndex != null ){\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( playButtonSongIndex );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}else{\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( config.active_index );\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playButtonPlaylistIndex );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\n\t\t\t*/\n\t\t\tif( ( playButtonPlaylistIndex == null || playButtonPlaylistIndex == '' )\n\t\t\t\t&& ( playButtonSongIndex != null && playButtonSongIndex != '' ) ){\n\n\t\t\t\t\tif( AmplitudeCoreHelpers.checkNewSong( playButtonSongIndex )\n\t\t\t\t\t\t|| config.active_playlist != playButtonPlaylistIndex ){\n\t\t\t\t\t\tAmplitudeCoreHelpers.changeSong( playButtonSongIndex );\n\t\t\t\t\t}\n\n\t\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( playButtonPlaylistIndex, playButtonSongIndex );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tStart the visualizations for the song.\n\t\t\t\tAMPFX-TODO: MAKE HANDLED BY AMPLITUDE FX\n\t\t\t*/\n\t\t\t//privateStartVisualization();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a pause button\n\t *\n\t * HANDLER FOR: 'amplitude-pause'\n\t *\n\t * @access public\n\t * @TODO Finish commenting and optimize\n\t */\n\tpause: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\tlet pauseButtonSongIndex = this.getAttribute('amplitude-song-index');\n\t\t\tlet pauseButtonPlaylistIndex = this.getAttribute('amplitude-playlist');\n\n\t\t\tif( pauseButtonSongIndex == null && pauseButtonPlaylistIndex == null ){\n\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( config.active_playlist, config.active_index );\n\t\t\t\tAmplitudeCore.pause();\n\t\t\t}\n\n\n\t\t\tif( pauseButtonPlaylistIndex != null || pauseButtonPlaylistIndex != ''\n\t\t\t\t&& config.active_playlist == pauseButtonPlaylistIndex ){\n\t\t\t\t/*\n\t\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\t\tto be paused and we pause the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t\t/*\n\t\t\t\t\tIf there is an active playlist, then\n\t\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\t\tbutton to the state of paused.\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t\t/*\n\t\t\t\t\tSync the song play pause buttons\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t\tAmplitudeCore.pause();\n\t\t\t}\n\n\t\t\tif( ( pauseButtonPlaylistIndex == null || pauseButtonPlaylistIndex == '' )\n\t\t\t\t&& ( pauseButtonSongIndex == config.active_index ) ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tThe song was playing so we sync visually for the song\n\t\t\t\t\t\tto be paused and we pause the song.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'paused' );\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf there is an active playlist, then\n\t\t\t\t\t\twe need to sync that playlist's play pause\n\t\t\t\t\t\tbutton to the state of paused.\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( config.active_playlist, 'paused' );\n\n\t\t\t\t\t/*\n\t\t\t\t\t\tSync the song play pause buttons\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( config.active_playlist, config.active_index, 'paused' );\n\n\t\t\t\t\tAmplitudeCore.pause();\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a play/pause button\n\t *\n\t * HANDLER FOR: 'amplitude-play-pause'\n\t *\n\t * @access public\n\t */\n\tplayPause: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tChecks to see if the element has an attribute for amplitude-main-play-pause\n\t\t\t\tand syncs accordingly\n\t\t\t*/\n\t\t\tif( this.getAttribute( 'amplitude-main-play-pause' ) != null ){\n\t\t\t\tAmplitudeEventsHelpers.setMainPlayPause();\n\n\t\t\t/*\n\t\t\t\tSyncs playlist main play pause buttons\n\t\t\t*/\n\t\t\t}else if( this.getAttribute('amplitude-playlist-main-play-pause') != null ){\n\t\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\n\t\t\t\tAmplitudeEventsHelpers.setPlaylistPlayPause( playlist );\n\n\t\t\t/*\n\t\t\t\tSyncs amplitude individual song buttons\n\t\t\t*/\n\t\t\t}else{\n\t\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\t\t\t\tlet songIndex \t= this.getAttribute('amplitude-song-index');\n\n\t\t\t\tAmplitudeEventsHelpers.setSongPlayPause( playlist, songIndex );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a stop element.\n\t *\n\t * HANDLER FOR: 'amplitude-stop'\n\t *\n\t * @access public\n\t * @TODO: AMP-FX Before stopping, make sure that AmplitudeFX visualization is stopped as well.\n\t */\n\tstop: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tSets all of the play/pause buttons to pause\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.setPlayPauseButtonsToPause();\n\n\t\t\t/*\n\t\t\t\tStops the active song.\n\t\t\t*/\n\t\t\tAmplitudeCore.stop();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event for a mute element\n\t *\n\t * HANDLER FOR: 'amplitude-mute'\n\t *\n\t * @access public\n\t */\n\tmute: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tIf the current volume in the config is 0, we set the volume to the\n\t\t\t\tpre_mute level. This means that the audio is already muted and\n\t\t\t\tneeds to be restored to the pre_mute level.\n\n\t\t\t\tOtherwise, we set pre_mute volume to the current volume\n\t\t\t\tand set the config volume to 0, muting the audio.\n\t\t\t*/\n\t\t\tif( config.volume == 0 ){\n\t\t\t\tconfig.active_song.muted = false;\n\t\t\t\tconfig.volume = config.pre_mute_volume;\n\t\t\t\tAmplitudeVisualSync.syncMute( false );\n\t\t\t}else{\n\t\t\t\tconfig.active_song.muted = true;\n\t\t\t\tconfig.pre_mute_volume = config.volume;\n\t\t\t\tconfig.volume = 0;\n\t\t\t\tAmplitudeVisualSync.syncMute( true );\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tCalls the core function to set the volume to the computed value\n\t\t\t\tbased on the user's intent.\n\t\t\t*/\n\t\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t\t/*\n\t\t\t\tSyncs the volume sliders so the visuals align up with the functionality.\n\t\t\t\tIf the volume is at 0, then the sliders should represent that so the user\n\t\t\t\thas the right starting point.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncVolumeSliders( config.volume );\n\t\t}\n\t},\n\n\t/**\n\t * Handles a click on a volume up element.\n\t *\n\t * HANDLER FOR: 'amplitude-volume-up'\n\t *\n\t * @access public\n\t */\n\tvolumeUp: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tThe volume range is from 0 to 1 for an audio element. We make this\n\t\t\t\ta base of 100 for ease of working with.\n\n\t\t\t\tIf the new value is less than 100, we use the new calculated\n\t\t\t\tvalue which gets converted to the proper unit for the audio element.\n\n\t\t\t\tIf the new value is greater than 100, we set the volume to 1 which\n\t\t\t\tis the max for the audio element.\n\t\t\t*/\n\t\t\tif( ( config.volume + config.volume_increment ) <= 100 ){\n\t\t\t\tconfig.volume = config.volume + config.volume_increment;\n\t\t\t}else{\n\t\t\t\tconfig.volume = 100;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tCalls the core function to set the volume to the computed value\n\t\t\t\tbased on the user's intent.\n\t\t\t*/\n\t\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t\t/*\n\t\t\t\tSyncs the volume sliders so the visuals align up with the functionality.\n\t\t\t\tIf the volume is at 0, then the sliders should represent that so the user\n\t\t\t\thas the right starting point.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncVolumeSliders( config.volume );\n\t\t}\n\t},\n\n\t/**\n\t * Handles a click on a volume down element.\n\t *\n\t * HANDLER FOR: 'amplitude-volume-down'\n\t *\n\t * @access public\n\t */\n\tvolumeDown: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tThe volume range is from 0 to 1 for an audio element. We make this\n\t\t\t\ta base of 100 for ease of working with.\n\n\t\t\t\tIf the new value is less than 100, we use the new calculated\n\t\t\t\tvalue which gets converted to the proper unit for the audio element.\n\n\t\t\t\tIf the new value is greater than 100, we set the volume to 1 which\n\t\t\t\tis the max for the audio element.\n\t\t\t*/\n\t\t\tif( ( config.volume - config.volume_increment ) > 0 ){\n\t\t\t\tconfig.volume = config.volume - config.volume_increment;\n\t\t\t}else{\n\t\t\t\tconfig.volume = 0;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tCalls the core function to set the volume to the computed value\n\t\t\t\tbased on the user's intent.\n\t\t\t*/\n\t\t\tAmplitudeCore.setVolume( config.volume );\n\n\t\t\t/*\n\t\t\t\tSyncs the volume sliders so the visuals align up with the functionality.\n\t\t\t\tIf the volume is at 0, then the sliders should represent that so the user\n\t\t\t\thas the right starting point.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncVolumeSliders( config.volume );\n\t\t}\n\t},\n\n\t/**\n\t * Handles a change on the song slider\n\t *\n\t * HANDLER FOR: 'amplitude-song-slider'\n\t *\n\t * @access public\n\t */\n\tsongSlider: function(){\n\t\t/*\n\t\t\tGets the percentage of the song we will be setting the location for.\n\t\t*/\n\t\tlet locationPercentage = this.value;\n\n\t\t/*\n\t\t\tChecks to see if the element has an attribute for amplitude-main-play-pause\n\t\t\tand syncs accordingly\n\t\t*/\n\t\tif( this.getAttribute( 'amplitude-main-song-slider' ) != null ){\n\t\t\t/*\n\t\t\t\tIf the active song is not live, set the current time\n\t\t\t*/\n\t\t\tif( !config.active_metadata.live ){\n\t\t\t\tlet currentTime = ( config.active_song.duration ) * ( locationPercentage / 100 );\n\n\t\t\t\tif( isFinite( currentTime ) ){\n\t\t\t\t\tconfig.active_song.currentTime = currentTime;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tAmplitudeVisualSync.syncMainSliderLocation( locationPercentage );\n\n\t\t\tif( config.active_playlist != '' && config.active_playlist != null ){\n\t\t\t\tAmplitudeVisualSync.syncPlaylistSliderLocation( config.active_playlist, locationPercentage );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tSyncs playlist main play pause buttons\n\t\t*/\n\t\tif( this.getAttribute('amplitude-playlist-song-slider') != null ){\n\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\n\t\t\t/*\n\t\t\t\tWe don't want to song slide a playlist that's not the\n\t\t\t\tactive placylist.\n\t\t\t*/\n\t\t\tif( config.active_playlist == playlist ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active song is not live, set the current time\n\t\t\t\t*/\n\t\t\t\tif( !config.active_metadata.live ){\n\t\t\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( locationPercentage / 100 );\n\t\t\t\t}\n\t\t\t\tAmplitudeVisualSync.syncMainSliderLocation( locationPercentage );\n\t\t\t\tAmplitudeVisualSync.syncPlaylistSliderLocation( playlist, locationPercentage );\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tSyncs amplitude individual song buttons\n\t\t*/\n\t\tif( this.getAttribute('amplitude-playlist-song-slider') == null\n\t\t\t&& this.getAttribute('amplitude-main-song-slider') == null ){\n\n\t\t\tlet playlist \t= this.getAttribute('amplitude-playlist');\n\t\t\tlet songIndex \t= this.getAttribute('amplitude-song-index');\n\n\t\t\tif( config.active_index == songIndex ){\n\t\t\t\t/*\n\t\t\t\t\tIf the active song is not live, set the current time\n\t\t\t\t*/\n\t\t\t\tif( !config.active_metadata.live ){\n\t\t\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( locationPercentage / 100 );\n\t\t\t\t}\n\n\t\t\t\tAmplitudeVisualSync.syncMainSliderLocation();\n\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& config.active_playlist == playlist ){\n\t\t\t\t\t\tAmplitudeVisualSync.syncPlaylistSliderLocation( playlist, location );\n\t\t\t\t}\n\n\t\t\t\tAmplitudeVisualSync.syncSongSliderLocation( playlist, songIndex, location );\n\t\t\t}\n\t\t}\n\n\t},\n\n\t/**\n\t * Handles a change on the volume slider\n\t *\n\t * HANDLER FOR: 'amplitude-volume-slider'\n\t *\n\t * @access public\n\t */\n\tvolumeSlider: function(){\n\t\t/*\n\t\t\tCalls the core function to set the volume to the computed value\n\t\t\tbased on the user's intent.\n\t\t*/\n\t\tAmplitudeCore.setVolume( this.value );\n\n\t\t/*\n\t\t\tSync the volume slider locations\n\t\t*/\n\t\tAmplitudeVisualSync.syncVolumeSliderLocation( this.value );\n\t},\n\n\t/**\n\t * Handles an event on the next button\n\t *\n\t * HANDLER FOR: 'amplitude-next'\n\t *\n\t * @access public\n\t */\n\tnext: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tChecks to see if the button is a playlist next button or\n\t\t\t\tif it's a global playlist button.\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\n\t\t\t\t/*\n\t\t\t\t\tCheck to see if the current state of the player\n\t\t\t\t\tis in playlist mode or not playlist mode.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\tAmplitudeEventsHelpers.setNext();\n\t\t\t\t}else{\n\t\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( config.active_playlist );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the playlist of the next button.\n\t\t\t\t*/\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\n\t\t\t\t/*\n\t\t\t\t\tSets the next playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( playlist );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the previous button\n\t *\n\t * HANDLER FOR: 'amplitude-prev'\n\t *\n\t * @access public\n\t */\n\tprev: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tChecks to see if the previous button is a playlist previous\n\t\t\t\tbutton or if it's a global playlist button.\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\n\t\t\t\t/*\n\t\t\t\t\tCheck to see if the current playlist has been set\n\t\t\t\t\tor null and set the previous song.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null ){\n\t\t\t\t\t\tAmplitudeEventsHelpers.setPrev();\n\t\t\t\t}else{\n\t\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( config.active_playlist );\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the playlist of the previous button.\n\t\t\t\t*/\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\n\t\t\t\t/*\n\t\t\t\t\tSets the previous playlist\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( playlist );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the shuffle button\n\t *\n\t * HANDLER FOR: 'amplitude-shuffle'\n\t *\n\t * @access public\n\t */\n\tshuffle: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tCheck to see if the shuffle button belongs to a playlist\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\t\t\t\t/*\n\t\t\t\t\tSets the shuffle button to null\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setShuffle( null );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the playlist attribute of the shuffle button and\n\t\t\t\t\tset shuffle to on for the playlist.\n\t\t\t\t*/\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\t\t\t\tAmplitudeEventsHelpers.setShuffle( playlist );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the repeat button\n\t *\n\t * HANDLER FOR: 'amplitude-repeat'\n\t *\n\t * @access private\n\t */\n\trepeat: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tCheck to see if the repeat button belongs to a playlist\n\t\t\t*/\n\t\t\tif( this.getAttribute('amplitude-playlist') == ''\n\t\t\t\t|| this.getAttribute('amplitude-playlist') == null ){\n\t\t\t\t\t/*\n\t\t\t\t\t\tSets repeat to the opposite of what it was set to\n\t\t\t\t\t*/\n\t\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat, null );\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tGets the playlist attribute of the repeat button and\n\t\t\t\t\t\tset repeat to on for the playlist.\n\t\t\t\t\t*/\n\t\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\t\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat_statuses[playlist], playlist );\n\t\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the repeat song button\n\t *\n\t * HANDLER FOR: 'amplitude-repeat-song'\n\t *\n\t * @access private\n\t */\n\trepeatSong: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tSets repeat song to the opposite of what it was set to\n\t\t\t*/\n\t\t\tAmplitudeEventsHelpers.setRepeatSong( !config.repeat_song );\n\n\t\t\t/*\n\t\t\t\tVisually sync repeat song\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncRepeatSong();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on the playback speed button\n\t *\n\t * HANDLER FOR: 'amplitude-playback-speed'\n\t *\n\t * @access private\n\t */\n\tplaybackSpeed: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tWe increment the speed by .5 everytime we click\n\t\t\t\tthe button to change the playback speed. Once we are\n\t\t\t\tactively playing back at 2, we start back at 1 which\n\t\t\t\tis normal speed.\n\t\t\t*/\n\t\t\tswitch( config.playback_speed ){\n\t\t\t\tcase 1:\n\t\t\t\t\tAmplitudeEventsHelpers.setPlaybackSpeed( 1.5 );\n\t\t\t\tbreak;\n\t\t\t\tcase 1.5:\n\t\t\t\t\tAmplitudeEventsHelpers.setPlaybackSpeed( 2 );\n\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tAmplitudeEventsHelpers.setPlaybackSpeed( 1 );\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t\tVisually sync the playback speed.\n\t\t\t*/\n\t\t\tAmplitudeVisualSync.syncPlaybackSpeed();\n\t\t}\n\t},\n\n\t/**\n\t * Handles an event on a skip to button.\n\t *\n\t * HANDLER FOR: 'amplitude-skip-to'\n\t *\n\t * @access private\n\t */\n\tskipTo: function(){\n\t\tif( !config.is_touch_moving ){\n\t\t\t/*\n\t\t\t\tDetermines if the skip to button is in the scope of a playlist.\n\t\t\t*/\n\t\t\tif( this.hasAttribute('amplitude-playlist') ){\n\t\t\t\tlet playlist = this.getAttribute('amplitude-playlist');\n\n\t\t\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\t\t\t\t}\n\t\t\t\t/*\n\t\t\t\t\tGets the location, playlist and song index that is being skipped\n\t\t\t\t\tto.\n\t\t\t\t*/\n\t\t\t\tlet seconds = parseInt( this.getAttribute('amplitude-location') );\n\t\t\t\tlet songIndex = parseInt( this.getAttribute( 'amplitude-song-index') );\n\n\t\t\t\t/*\n\t\t\t\t\tChanges the song to where it's being skipped and then\n\t\t\t\t\tplay the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t\t\tAmplitudeCore.play();\n\n\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( playlist, 'playing' );\n\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, songIndex, 'playing' );\n\n\t\t\t\t/*\n\t\t\t\t\tSkip to the location in the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCore.skipToLocation( seconds );\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGets the location and song index that is being skipped\n\t\t\t\t\tto.\n\t\t\t\t*/\n\t\t\t \tlet seconds = parseInt( this.getAttribute('amplitude-location') );\n\t\t\t \tlet songIndex = parseInt( this.getAttribute( 'amplitude-song-index') );\n\n\t\t\t\t/*\n\t\t\t\t\tChanges the song to where it's being skipped and then\n\t\t\t\t\tplay the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\t\t\tAmplitudeCore.play();\n\n\t\t\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\t\t\t\tAmplitudeVisualSync.syncSongPlayPause( null, songIndex, 'playing' );\n\n\t\t\t\t/*\n\t\t\t\t\tSkip to the location in the song.\n\t\t\t\t*/\n\t\t\t\tAmplitudeCore.skipToLocation( seconds );\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/events/handlers.js","/**\n * @name \t\tAmplitude.js\n * @version 3.3.0\n * @author \tDan Pastori (521 Dimensions) \n*/\n\n/**\n * AmplitudeJS Initializer Module\n *\n * @module init/AmplitudeInitializer\n */\nimport AmplitudeInitializer from './init/init.js';\n\n/**\n * AmplitudeJS Core Module\n *\n * @module core/AmplitudeCore\n */\nimport AmplitudeCore from './core/core.js';\n\n/**\n * AmplitudeJS Core Helpers Module\n *\n * @module core/AmplitudeCoreHelpers\n */\nimport AmplitudeCoreHelpers from './core/helpers.js';\n\n/**\n * AmplitudeJS Events Module\n *\n * @module events/AmplitudeEvents\n */\nimport AmplitudeEvents from './events/events.js';\n\n/**\n * AmplitudeJS Events Helpers Module\n *\n * @module events/AmplitudeEventsHelpers\n */\nimport AmplitudeEventsHelpers from './events/helpers.js';\n\n/**\n * AmplitudeJS Visual Sync Module\n *\n * @module visual/AmplitudeVisualSync\n */\nimport AmplitudeVisualSync from './visual/visual.js';\n\n/**\n * Imports the config module\n * @module config\n */\nimport config from './config.js';\n\n/**\n * Amplitude should just be an interface to the public functions.\n * Everything else should be handled by other objects\n *\n * @module Amplitude\n */\n\nlet Amplitude = (function () {\n\t/**\n\t * The main init function. The user will call this through\n\t * Amplitude.init({}) and pass in their settings.\n\t *\n\t * Public Accessor: Amplitude.init( user_config_json );\n\t *\n\t * @access public\n\t * @param {object} userConfig \t- A JSON object of user defined values that helps configure and initialize AmplitudeJS.\n\t */\n\tfunction init( userConfig ){\n\t\tAmplitudeInitializer.initialize( userConfig );\n\t}\n\n\t/**\n\t * Binds new elements that were added to the page.\n\t *\n\t * Public Accessor: Amplitude.bindNewElements()\n\t *\n\t * @access public\n\t */\n\tfunction bindNewElements(){\n\t\tAmplitudeInitializer.rebindDisplay();\n\t}\n\n\t/**\n\t * Returns the active playlist.\n\t *\n\t * Public Accessor: Amplitude.getActivePlaylist()\n\t *\n\t * @access public\n\t */\n\tfunction getActivePlaylist(){\n\t\treturn config.active_playlist;\n\t}\n\n\t/**\n\t * Returns the current playback speed.\n\t *\n\t * Public Accessor: Amplitude.getPlaybackSpeed()\n\t *\n\t * @access public\n\t */\n\tfunction getPlaybackSpeed(){\n\t\treturn config.playback_speed;\n\t}\n\n\t/**\n\t * Gets the repeat state of the player.\n\t *\n\t * Public Accessor: Amplitude.getRepeat()\n\t *\n\t * @access public\n\t */\n\tfunction getRepeat(){\n\t\treturn config.repeat;\n\t}\n\n\t/**\n\t * Returns the shuffle state of the player.\n\t *\n\t * Public Accessor: Amplitude.getShuffle()\n\t *\n\t * @access public\n\t */\n\tfunction getShuffle(){\n\t\treturn config.shuffle_on\n\t}\n\n\t/**\n\t * Returns the shuffle state of the playlist.\n\t *\n\t * Public Accessor: Amplitude.getShufflePlaylist( playlist )\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The key representing the playlist ID to see if it's shuffled or not.\n\t */\n\tfunction getShufflePlaylist( playlist ){\n\t\treturn config.shuffled_statuses[ playlist ];\n\t}\n\n\t/**\n\t * Sets the shuffle state for the player.\n\t *\n\t * Public Accessor: Amplitude.setShuffle()\n\t *\n\t * @access public\n\t */\n\t function setShuffle(){\n\t\t AmplitudeEventsHelpers.setShuffle( null );\n\t }\n\n\t /**\n \t * Sets the shuffle state for the playlist\n \t *\n \t * Public Accessor: Amplitude.setShufflePlaylist( playlistKey )\n \t *\n \t * @access public\n\t * @param {string} playlistKey \t- The key representing the playlist ID to to shuffle the playlist.\n \t */\n \t function setShufflePlaylist( playlistKey ){\n \t\t AmplitudeEventsHelpers.setShuffle( playlistKey );\n \t }\n\n\t /**\n\t * Sets the repeat state for the player.\n\t\t*\n\t\t* Public Accessor: Amplitude.setRepeat()\n\t\t*\n\t\t* @access public\n\t */\n\t\tfunction setRepeat(){\n\t\t\tif( !config.is_touch_moving ){\n\t\t\t\t/*\n\t\t\t\t\tSets repeat to the opposite of what it was set to\n\t\t\t\t*/\n\t\t\t\tAmplitudeEventsHelpers.setRepeat( !config.repeat );\n\n\t\t\t\t/*\n\t\t\t\t\tVisually sync repeat\n\t\t\t\t*/\n\t\t\t\tAmplitudeVisualSync.syncRepeat();\n\t\t\t}\n\t\t}\n\n\t/**\n\t * Sets the repeat state for the song.\n\t *\n\t * Public Accessor: Amplitude.setRepeatSong()\n\t *\n\t * @access public\n\t */\n\t function setRepeatSong(){\n\t\t if( !config.is_touch_moving ){\n\t\t\t /*\n\t\t\t\t Sets repeat to the opposite of what it was set to\n\t\t\t */\n\t\t\t AmplitudeEventsHelpers.setRepeatSong( !config.repeat_song );\n\n\t\t\t /*\n\t\t\t\t Visually sync repeat song\n\t\t\t */\n\t\t\t AmplitudeVisualSync.syncRepeatSong();\n\t\t }\n\t }\n\n\n\t/**\n\t * Gets the default album art for the player\n\t *\n\t * Public Accessor: Amplitude.getDefaultAlbumArt()\n\t *\n\t * @access public\n\t */\n\tfunction getDefaultAlbumArt(){\n\t\treturn config.default_album_art;\n\t}\n\n\t/**\n\t * Sets the default album art for the player\n\t *\n\t * Public Accessor: Amplitude.setDefaultAlbumArt( url )\n\t *\n\t * @access public\n\t * @param {string} url \t- A string representing the URL of the new default album art.\n\t */\n\tfunction setDefaultAlbumArt( url ){\n\t\tconfig.default_album_art = url;\n\t}\n\n\t/**\n\t * Allows the user to get the percentage of the song played.\n\t *\n\t * Public Accessor: Amplitude.getSongPlayedPercentage();\n\t *\n\t * @access public\n\t */\n\tfunction getSongPlayedPercentage(){\n\t\t/*\n\t\t\tReturns the percentage of the song played.\n\t\t*/\n\t\treturn ( config.active_song.currentTime / config.active_song.duration ) * 100;\n\t}\n\n\t/**\n\t * Allows the user to set how far into the song they want to be. This is\n\t * helpful for implementing custom range sliders. Only works on the current song.\n\t *\n\t * Public Accessor: Amplitude.setSongPlayedPercentage( float );\n\t *\n\t * @access public\n\t * @param {number} percentage \t- The percentage of the song played\n\t */\n\tfunction setSongPlayedPercentage( percentage ){\n\t\t/*\n\t\t\tEnsures the percentage is a number and is between 0 and 100.\n\t\t*/\n\t\tif( typeof percentage == 'number'\n\t\t\t&& ( percentage > 0 && percentage < 100 ) ){\n\t\t\t\t/*\n\t\t\t\t\tSets the current time of the song to the percentage.\n\t\t\t\t*/\n\t\t\t\tconfig.active_song.currentTime = ( config.active_song.duration ) * ( percentage / 100 );\n\t\t}\n\t}\n\n\t/**\n\t * Allows the user to turn on debugging.\n\t *\n\t * Public Accessor: Amplitude.setDebug( bool );\n\t *\n\t * @access public\n\t * @param {boolean} state \t\t- Turns debugging on and off.\n\t */\n\tfunction setDebug( state ){\n\t\t/*\n\t\t\tSets the global config debug on or off.\n\t\t*/\n\t\tconfig.debug = state;\n\t}\n\n\t/**\n\t * Returns the active song meta data for the user to do what is\n\t * needed.\n\t *\n\t * Public Accessor: Amplitude.getActiveSongMetadata();\n\t *\n\t * @access public\n\t * @returns {object} JSON Object with the active song information\n\t */\n\tfunction getActiveSongMetadata(){\n\t\treturn config.active_metadata;\n\t}\n\n\t/**\n\t * Returns a song in the songs array at that index\n\t *\n\t * Public Accessor: Amplitude.getSongByIndex( song_index )\n\t *\n\t * @access public\n\t * @param {number} index \t- The integer for the index of the song in the songs array.\n\t * @returns {object} JSON representation for the song at a specific index.\n\t */\n\tfunction getSongByIndex( index ){\n\t\treturn config.songs[index];\n\t}\n\n\t/**\n\t * Returns a song at a playlist index\n\t *\n\t * Public Accessor: Amplitude.getSongAtPlaylistIndex( playlist, index\n\t *\n\t * @access public\n\t * @param {number} index \t\t\t- The integer for the index of the song in the playlist.\n\t * @param {string} playlist\t\t- The key of the playlist we are getting the song at the index for\n\t * @returns {object} JSON representation for the song at a specific index.\n\t */\n\tfunction getSongAtPlaylistIndex( playlist, index ){\n\t\tlet songIndex = config.playlists[playlist][index];\n\n\t\treturn config.songs[songIndex];\n\t}\n\n\t/**\n\t * Adds a song to the end of the config array. This will allow Amplitude\n\t * to play the song in a playlist type setting.\n\t *\n\t * Public Accessor: Amplitude.addSong( song_json )\n\t *\n\t * @access public\n\t * @param {object} song \t- JSON representation of a song.\n\t * @returns {number} New index of the song.\n\t */\n\tfunction addSong( song ){\n\t\t/*\n\t\t\tEnsures we have a songs array to push to.\n\t\t*/\n\t\tif( config.songs == undefined ){\n\t\t\tconfig.songs = [];\n\t\t}\n\n\t\tconfig.songs.push( song );\n\t\tAmplitudeEventsHelpers.setNext();\n\t\treturn config.songs.length - 1;\n\t}\n\n\t/**\n\t * Adds a song to a playlist. This will allow Amplitude to play the song in the\n\t * playlist\n\t *\n\t * Public Accessor: Amplitude.addSongToPlaylist( song_json, playlist_key )\n\t *\n\t * @access public\n\t * @param {object} song \t\t\t- JSON representation of a song.\n\t * @param {string} playlist\t\t- Playlist we are adding the song to.\n\t * @returns {mixed} New index of song in playlist or null if no playlist exists\n\t */\n\t function addSongToPlaylist( song, playlist ){\n\t\t \t/*\n\t \t\t\tEnsures we have a songs array to push to. This is step 1.\n\t \t\t*/\n\t \t\tif( config.songs == undefined ){\n\t \t\t\tconfig.songs = [];\n\t \t\t}\n\n\t \t\tconfig.songs.push( song );\n\n\t\t\tvar songIndex = config.songs.length - 1;\n\n\t\t\t/*\n\t\t\t\tEnsures the playlist is valid to push the song on to.\n\t\t\t*/\n\t\t\tif( config.playlists[playlist] != undefined ){\n\t\t\t\tconfig.playlists[playlist].push( songIndex );\n\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( playlist );\n\n\t\t\t\treturn config.playlists[playlist].length - 1;\n\t\t\t}else{\n\t\t\t\treturn null;\n\t\t\t}\n\t }\n\n\t /**\n \t * Removes a song from the song array\n \t *\n \t * Public Accessor: Amplitude.removeSong( index )\n \t *\n \t * @access public\n \t * @param {integer} index \t\t\t- Index of the song being removed\n \t * @returns {boolean} True if removed false if not.\n \t */\n\t function removeSong( index ){\n\t\t if( config.songs[index] != undefined ){\n\t\t\t config.songs.splice( index, 1 );\n\t\t\t return true;\n\t\t }else{\n\t\t \treturn false;\n\t\t }\n\t }\n\n\t /**\n \t * Removes a song from the playlist\n \t *\n \t * Public Accessor: Amplitude.removeSongFromPlaylist( index, playlist )\n \t *\n \t * @access public\n \t * @param {integer} index \t\t\t- Index of the song being removed from the playlist.\n \t * @param {string} playlist\t\t\t- Playlist we are removing the song from.\n \t * @returns {boolean} True if removed false if not.\n \t */\n\t function removeSongFromPlaylist( index, playlist ){\n\t\t if( config.playlists[playlist] != undefined ){\n\t\t\t config.playlists[playlist].splice( index, 1 );\n\t\t }else{\n\t\t\t return false;\n\t\t }\n\t }\n\n\t/**\n\t * When you pass a song object it plays that song right awawy. It sets\n\t * the active song in the config to the song you pass in and synchronizes\n\t * the visuals.\n\t *\n\t * Public Accessor: Amplitude.playNow( song )\n\t *\n\t * @access public\n\t * @param {object} song \t- JSON representation of a song.\n\t */\n\tfunction playNow( song ){\n\t\tAmplitudeCore.playNow( song );\n\t}\n\n\t/**\n\t * Plays a song at the index passed in from the songs array.\n\t *\n\t * Public Accessor: Amplitude.playSongAtIndex( index )\n\t *\n\t * @access public\n\t * @param {number} index \t- The number representing the song in the songs array.\n\t */\n\tfunction playSongAtIndex( index ){\n\t\tAmplitudeCore.playSongAtIndex( index );\n\t}\n\n\t/**\n\t * Plays a song at the index passed in for the playlist provided. The index passed\n\t * in should be the index of the song in the playlist and not the songs array.\n\t *\n\t * @access public\n\t * @param {number} index \t\t- The number representing the song in the playlist array.\n\t * @param {string} playlist - The key string representing the playlist we are playing the song from.\n\t *\n\t */\n\tfunction playPlaylistSongAtIndex( index, playlist ){\n\t\tAmplitudeCore.playPlaylistSongAtIndex( index, playlist );\n\t}\n\n\t/**\n\t * @TODO: Implement Add Song To Playlist Functionality\n\t */\n\tfunction addSongToPlaylist( song, playlist ){\n\n\t}\n\n\t/**\n\t * Allows the user to play whatever the active song is directly\n\t * through Javascript. Normally ALL of Amplitude functions that access\n\t * the core features are called through event handlers.\n\t *\n\t * Public Accessor: Amplitude.play();\n\t *\n\t * @access public\n\t */\n\tfunction play(){\n\t\tAmplitudeCore.play();\n\t}\n\n\t/**\n\t * Allows the user to pause whatever the active song is directly\n\t * through Javascript. Normally ALL of Amplitude functions that access\n\t * the core features are called through event handlers.\n\t *\n\t * Public Accessor: Amplitude.pause();\n\t *\n\t * @access public\n\t */\n\tfunction pause(){\n\t\tAmplitudeCore.pause();\n\t}\n\n\t/**\n\t * Returns the audio object used to play the audio\n\t *\n\t * Public Accessor: Amplitude.getAudio();\n\t *\n\t * @access public\n\t */\n\tfunction getAudio(){\n\t\treturn config.active_song;\n\t}\n\n\t/**\n\t * Plays the next song either in the playlist or globally.\n\t *\n\t * Public Accessor: Amplitude.next( playlist );\n\t *\n\t * @access public\n\t * @param {string} [playlist = null] \t- The playlist key\n\t */\n\tfunction next( playlist = null ){\n\t\t/*\n\t\t\tIf the playlist is empty or null, then we check the active\n\t\t\tplaylist\n\t\t*/\n\t\tif( playlist == '' || playlist == null ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is null, then we set the next global\n\t\t\t\tsong or we set the next in the playlist.\n\t\t\t*/\n\t\t\tif( config.active_playlist == null || config.active_playlist == '' ){\n\t\t\t\tAmplitudeEventsHelpers.setNext()\n\t\t\t}else{\n\t\t\t\tAmplitudeEventsHelpers.setNextPlaylist( config.active_playlist );\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tSet the next in the playlist for the key provided.\n\t\t\t*/\n\t\t\tAmplitudeEventsHelpers.setNextPlaylist( playlist );\n\t\t}\n\t}\n\n\t/**\n\t * Plays the prev song either in the playlist or globally.\n\t *\n\t * Public Accessor: Amplitude.prev( playlist );\n\t *\n\t * @access public\n\t * @param {string} [playlist = null] \t- The playlist key\n\t */\n\tfunction prev( playlist = null ){\n\t\t/*\n\t\t\tIf the playlist is empty or null, then we check the active\n\t\t\tplaylist\n\t\t*/\n\t\tif( playlist == '' || playlist == null ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is null, then we set the prev global\n\t\t\t\tsong or we set the prev in the playlist.\n\t\t\t*/\n\t\t\tif( config.active_playlist == null || config.active_playlist == '' ){\n\t\t\t\tAmplitudeEventsHelpers.setPrev()\n\t\t\t}else{\n\t\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( config.active_playlist );\n\t\t\t}\n\t\t}else{\n\t\t\t/*\n\t\t\t\tSet the prev in the playlist for the key provided.\n\t\t\t*/\n\t\t\tAmplitudeEventsHelpers.setPrevPlaylist( playlist );\n\t\t}\n\t}\n\n\t/**\n\t * Gets all of the songs in the songs array\n\t *\n\t * Public Accessor: Amplitude.getSongs( );\n\t *\n\t * @access public\n\t */\n\tfunction getSongs(){\n\t\treturn config.songs;\n\t}\n\n\t/**\n\t * Gets all of the songs in a playlist\n\t *\n\t * Public Accessor: Amplitude.getSongsInPlaylist( playlist );\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist key\n\t */\n\tfunction getSongsInPlaylist( playlist ){\n\t\tlet songsArray = [];\n\n\t\tfor( let i = 0; i < config.playlists[playlist].length; i++ ){\n\t\t\tlet songIndex = config.playlists[playlist][i];\n\t\t\tsongsArray.push( config.songs[songIndex] );\n\t\t}\n\n\t\treturn songsArray;\n\t}\n\n\t/**\n\t * Get current state of songs. If shuffled, this will return the shuffled\n\t * songs.\n\t *\n\t * Public Accessor: Amplitude.getSongsState();\n\t *\n\t * @access public\n\t */\n\tfunction getSongsState(){\n\t\tif( config.shuffle_on ){\n\t\t\treturn config.shuffle_list;\n\t\t}else{\n\t\t\treturn config.songs;\n\t\t}\n\t}\n\n\t/**\n\t * Get current state of songs in playlist. If shuffled, this will return the\n\t * shuffled songs.\n\t *\n\t * Public Accessor: Amplitude.getSongsStatePlaylist( playlist );\n\t *\n\t * @access public\n\t * @param {string} playlist \t- The playlist key\n\t * @todo Finish commenting\n\t */\n\tfunction getSongsStatePlaylist( playlist ){\n\t\tlet songsArray = [];\n\n\t\tif( config.shuffled_status[playlist] ){\n\n\t\t\tfor( let i = 0; i < config.shuffled_playlists[playlist].length; i++ ){\n\t\t\t\tsongsArray.push( config.songs[i] );\n\t\t\t}\n\n\t\t}else{\n\n\t\t\tfor( let i = 0; i < config.playlists[playlist].length; i++ ){\n\t\t\t\tsongsArray.push( config.songs[i] );\n\t\t\t}\n\t\t}\n\n\t\treturn songsArray;\n\t}\n\n\t/**\n\t * Gets the active index of the player\n\t *\n\t * Public Accessor: Amplitude.getActiveIndex()\n\t *\n\t * @access public\n\t */\n\tfunction getActiveIndex(){\n\t\treturn parseInt( config.active_index );\n\t}\n\n\t/**\n\t * Gets the active index with respect to the state of the player whether it is\n\t * shuffled or not.\n\t *\n\t * Public Accessor: Amplitude.getActiveIndexState()\n\t *\n\t * @access public\n\t */\n\tfunction getActiveIndexState(){\n\t\tif( config.shuffle_on ){\n\t\t\treturn parseInt( config.shuffle_active_index );\n\t\t}else{\n\t\t\treturn parseInt( config.active_index );\n\t\t}\n\t}\n\n\t/**\n\t * Get the version of AmplitudeJS\n\t *\n\t * Public Accessor: Amplitude.getVersion()\n\t *\n\t * @access public\n\t */\n\tfunction getVersion(){\n\t\treturn config.version;\n\t}\n\n\t/**\n\t * Get the buffered amount for the current song\n\t *\n\t * Public Accessor: Amplitude.getBuffered()\n\t *\n\t * @access public\n\t */\n\tfunction getBuffered(){\n\t\treturn config.buffered;\n\t}\n\n\t/**\n\t * Skip to a certain location in a selected song.\n\t *\n\t * Public Accessor: Amplitude.getBuffered()\n\t *\n\t * @access public\n\t * @param {number} seconds \t\t\t\t\t\t- The amount of seconds we should skip to in the song.\n\t * @param {number} songIndex \t\t\t\t\t- The index of the song in the songs array.\n\t * @param {string} [playlist = null]\t- The playlist the song we are skipping to belogns to.\n\t */\n\tfunction skipTo( seconds, songIndex, playlist = null ){\n\t\tif( playlist != null ){\n\t\t\tif( AmplitudeCoreHelpers.checkNewPlaylist( playlist ) ){\n\t\t\t\tAmplitudeCoreHelpers.setActivePlaylist( playlist );\n\t\t\t}\n\t\t}\n\n\t\tseconds = parseInt( seconds );\n\n\t\t/*\n\t\t\tChanges the song to where it's being skipped and then\n\t\t\tplay the song.\n\t\t*/\n\t\tAmplitudeCoreHelpers.changeSong( songIndex );\n\t\tAmplitudeCore.play();\n\n\t\tAmplitudeVisualSync.syncMainPlayPause( 'playing' );\n\n\t\tif( playlist != null ){\n\t\t\tAmplitudeVisualSync.syncPlaylistPlayPause( playlist, 'playing' );\n\t\t}\n\n\t\tAmplitudeVisualSync.syncSongPlayPause( playlist, songIndex, 'playing' );\n\n\t\t/*\n\t\t\tSkip to the location in the song.\n\t\t*/\n\t\tAmplitudeCore.skipToLocation( seconds );\n\t}\n\n\t/*\n\t\tReturns all of the publically accesible methods.\n\t*/\n\treturn {\n\t\tinit: init,\n\t\tbindNewElements: bindNewElements,\n\t\tgetActivePlaylist: getActivePlaylist,\n\t\tgetPlaybackSpeed: getPlaybackSpeed,\n\t\tgetRepeat: getRepeat,\n\t\tgetShuffle: getShuffle,\n\t\tgetShufflePlaylist: getShufflePlaylist,\n\t\tsetShuffle: setShuffle,\n\t\tsetShufflePlaylist: setShufflePlaylist,\n\t\tsetRepeat: setRepeat,\n\t\tsetRepeatSong: setRepeatSong,\n\t\tgetDefaultAlbumArt: getDefaultAlbumArt,\n\t\tsetDefaultAlbumArt: setDefaultAlbumArt,\n\t\tgetSongPlayedPercentage: getSongPlayedPercentage,\n\t\tsetSongPlayedPercentage: setSongPlayedPercentage,\n\t\tsetDebug: setDebug,\n\t\tgetActiveSongMetadata: getActiveSongMetadata,\n\t\tgetSongByIndex: getSongByIndex,\n\t\tgetSongAtPlaylistIndex: getSongAtPlaylistIndex,\n\t\taddSong: addSong,\n\t\taddSongToPlaylist: addSongToPlaylist,\n\t\tremoveSong: removeSong,\n\t\tremoveSongFromPlaylist: removeSongFromPlaylist,\n\t\tplayNow: playNow,\n\t\tplaySongAtIndex: playSongAtIndex,\n\t\tplayPlaylistSongAtIndex: playPlaylistSongAtIndex,\n\t\tplay: play,\n\t\tpause: pause,\n\t\taudio: getAudio,\n\t\tnext: next,\n\t\tprev: prev,\n\t\tgetSongs: getSongs,\n\t\tgetSongsInPlaylist: getSongsInPlaylist,\n\t\tgetSongsState: getSongsState,\n\t\tgetSongsStatePlaylist: getSongsStatePlaylist,\n\t\tgetActiveIndex: getActiveIndex,\n\t\tgetActiveIndexState: getActiveIndexState,\n\t\tgetVersion: getVersion,\n\t\tgetBuffered: getBuffered,\n\t\tskipTo: skipTo\n\t}\n})();\n\nexport default Amplitude;\n\n\n\n// WEBPACK FOOTER //\n// ./src/index.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * Imports the helper functions for the core module\n * @module core/AmplitudeHelers\n */\nimport AmplitudeHelpers from '../core/helpers.js';\n\n/**\n * Imports the initializer\n * @module init/AmplitudeInitializer\n */\nimport AmplitudeInitializer from '../init/init.js';\n\n/**\n * These helpers wrap around the basic methods of the Soundcloud API\n * and get the information we need from SoundCloud to make the songs\n * streamable through Amplitude\n *\n * @module soundcloud/AmplitudeSoundcloud\n */\nlet AmplitudeSoundcloud = (function() {\n\n\t/**\n\t * Defines the temporary user config used while we configure soundcloud\n\t * @type {object}\n\t */\n\tlet tempUserConfig = {};\n\n\t/**\n\t * Loads the soundcloud SDK for use with Amplitude so the user doesn't have\n\t * to load it themselves.\n\t * With help from: http://stackoverflow.com/questions/950087/include-a-javascript-file-in-another-javascript-file\n\t *\n\t * @access public\n\t * @param {object} userConfig \t- The config defined by the user for AmplitudeJS\n\t */\n\tfunction loadSoundCloud( userConfig ){\n\t\t/*\n\t\t\tSets the temporary config to the config passed by the user so we can make changes\n\t\t\tand not break the actual config.\n\t\t*/\n\t\ttempUserConfig = userConfig;\n\n\t\t/*\n\t\t\tGets the head tag for the document and create a script element.\n\t\t*/\n\t\tlet head = document.getElementsByTagName('head')[0];\n\t\tlet script = document.createElement('script');\n\n\t\tscript.type = 'text/javascript';\n\n\t\t/*\n\t\t\tURL to the remote soundcloud SDK\n\t\t*/\n\t\tscript.src = 'https://connect.soundcloud.com/sdk.js';\n\t\tscript.onreadystatechange = initSoundcloud;\n\t\tscript.onload = initSoundcloud;\n\n\t\t/*\n\t\t\tAdd the script to the head of the document.\n\t\t*/\n\t\thead.appendChild( script );\n\t}\n\n\t/**\n\t * Initializes soundcloud with the key provided.\n\t *\n\t * @access private\n\t */\n\tfunction initSoundcloud(){\n\t\t/*\n\t\t\tCalls the SoundCloud initialize function\n\t\t\tfrom their API and sends it the client_id\n\t\t\tthat the user passed in.\n\t\t*/\n\t\tSC.initialize({\n\t\t\tclient_id: config.soundcloud_client\n\t\t});\n\n\t\t/*\n\t\t\tGets the streamable URLs to run through Amplitue. This is\n\t\t\tVERY important since Amplitude can't stream the copy and pasted\n\t\t\tlink from the SoundCloud page, but can resolve the streaming\n\t\t\tURLs from the link.\n\t\t*/\n\t\tgetStreamableURLs();\n\t}\n\n\t/**\n\t * Gets the streamable URL from the URL provided for\n\t * all of the soundcloud links. This will loop through\n\t * and set all of the information for the soundcloud\n\t * urls.\n\t *\n\t * @access private\n\t */\n\tfunction getStreamableURLs(){\n\t\t/*\n\t\t\tDefine the regex to find the soundcloud URLs\n\t\t*/\n\t\tlet soundcloud_regex = /^https?:\\/\\/(soundcloud.com|snd.sc)\\/(.*)$/;\n\n\t\tfor( let i = 0; i < config.songs.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the URL matches soundcloud, we grab\n\t\t\t\tthat url and get the streamable link\n\t\t\t\tif there is one.\n\t\t\t*/\n\t\t\tif( config.songs[i].url.match( soundcloud_regex ) ){\n\t\t\t\tconfig.soundcloud_song_count++;\n\t\t\t\tresolveStreamable(config.songs[i].url, i);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Due to Soundcloud SDK being asynchronous, we need to scope the\n\t * index of the song in another function. The privateGetSoundcloudStreamableURLs\n\t * function does the actual iteration and scoping.\n\t *\n\t * @access private\n\t * @param {string} url \t\t- URL of the soundcloud song\n\t * @param {number} index \t- The index of the soundcloud song in the songs array.\n\t */\n\tfunction resolveStreamable( url, index ){\n\t\tSC.get('/resolve/?url='+url, function( sound ){\n\t\t\t/*\n\t\t\t\tIf streamable we get the url and bind the client ID to the end\n\t\t\t\tso Amplitude can just stream the song normally. We then overwrite\n\t\t\t\tthe url the user provided with the streamable URL.\n\t\t\t*/\n\t\t\tif( sound.streamable ){\n\t\t\t\tconfig.songs[index].url = sound.stream_url+'?client_id='+config.soundcloud_client;\n\n\t\t\t\t/*\n\t\t\t\t\tIf the user want's to use soundcloud art, we overwrite the\n\t\t\t\t\tcover_art_url with the soundcloud artwork url.\n\t\t\t\t*/\n\t\t\t\tif( config.soundcloud_use_art ){\n\t\t\t\t\tconfig.songs[index].cover_art_url = sound.artwork_url;\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t\tGrab the extra metadata from soundcloud and bind it to the\n\t\t\t\t\tsong. The user can get this through the public function:\n\t\t\t\t\tgetActiveSongMetadata\n\t\t\t\t*/\n\t\t\t\tconfig.songs[index].soundcloud_data = sound;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf not streamable, then we print a message to the user stating\n\t\t\t\t\tthat the song with name X and artist X is not streamable. This\n\t\t\t\t\tgets printed ONLY if they have debug turned on.\n\t\t\t\t*/\n\t\t\t\tAmplitudeHelpers.writeDebugMessage( config.songs[index].name +' by '+config.songs[index].artist +' is not streamable by the Soundcloud API' );\n\t\t\t}\n\t\t\t/*\n\t\t\t\tIncrements the song ready counter.\n\t\t\t*/\n\t\t\tconfig.soundcloud_songs_ready++;\n\n\t\t\t/*\n\t\t\t\tWhen all songs are accounted for, then amplitude is ready\n\t\t\t\tto rock and we set the rest of the config.\n\t\t\t*/\n\t\t\tif( config.soundcloud_songs_ready == config.soundcloud_song_count ){\n\t\t\t\tAmplitudeInitializer.setConfig( tempUserConfig );\n\t\t\t}\n\t\t});\n\t}\n\n\t/*\n\t\tReturns the publically accessible methods\n\t*/\n\treturn {\n\t\tloadSoundCloud: loadSoundCloud\n\t}\n})();\n\nexport default AmplitudeSoundcloud\n\n\n\n// WEBPACK FOOTER //\n// ./src/soundcloud/soundcloud.js","/**\n * Imports the config module\n * @module config\n */\nimport config from '../config.js';\n\n/**\n * These methods help sync visual displays. They essentially make the visual sync\n * methods smaller and more maintainable.\n *\n * @module visual/AmplitudeVisualSyncHelpers\n */\nlet AmplitudeVisualSyncHelpers = (function() {\n\t/**\n\t * Updates any elements that display the current hour for the song.\n\t *\n\t * @access public\n\t * @param {number} hours \t- An integer conaining how many hours into the song.\n\t */\n\tfunction syncCurrentHours( hours ){\n\t\t/*\n\t\t\tGets all of the song hour selectors.\n\t\t*/\n\t\tlet hourSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-current-hours[amplitude-main-current-hours=\"true\"]',\n\t\t\t\t'.amplitude-current-hours[amplitude-playlist-current-hours=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-current-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-current-hours[amplitude-main-current-hours=\"true\"]',\n\t\t\t\t'.amplitude-current-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tEnsures that there are some hour selectors.\n\t\t*/\n\t\tif( document.querySelectorAll( hourSelectors.join() ).length > 0 ){\n\t\t\t/*\n\t\t\t\tGet all of the hour selectors\n\t\t\t*/\n\t\t\tconst currentHourSelectors = document.querySelectorAll( hourSelectors.join() );\n\n\t\t\t/*\n\t\t\t\tSet the current hour selector's inner html to hours passed in.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < currentHourSelectors.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tIf the selector is a main selector, we set the hours.\n\t\t\t\t*/\n\t\t\t\tif( currentHourSelectors[i].getAttribute('amplitude-main-current-hours') == 'true' ){\n\t\t\t\t\tcurrentHourSelectors[i].innerHTML = hours;\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t\t&& currentHourSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\t\tcurrentHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\t\tdoes not have a playlist then we set the hours. This\n\t\t\t\t\t\tmeans that the current selector is an individual song\n\t\t\t\t\t\tselector.\n\t\t\t\t\t*/\n\t\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t\t&& !currentHourSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\t\tcurrentHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t\t*/\n\t\t\t\t\t}else{\n\t\t\t\t\t\tcurrentHourSelectors[i].innerHTML = '0';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/*--------------------------------------------------------------------------\n\t\tResets the current hours displays to 0\n\t--------------------------------------------------------------------------*/\n\tfunction resetCurrentHours(){\n\t\t/*\n\t\t\tGets the hour display elements\n\t\t*/\n\t\tlet hourSelectors = document.querySelectorAll('.amplitude-current-hours');\n\n\t\t/*\n\t\t\tIterates over all of the hour selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( var i = 0; i < hourSelectors.length; i++ ){\n\t\t\thourSelectors[i].innerHTML = '0';\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the current minutes for the song.\n\t *\n\t * @access public\n\t * @param {number} minutes \t- An integer conaining how many minutes into the song.\n\t */\n\tfunction syncCurrentMinutes( minutes ){\n\t\t/*\n\t\t\tGets all of the song minute selectors.\n\t\t*/\n\t\tlet minuteSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-current-minutes[amplitude-main-current-minutes=\"true\"]',\n\t\t\t\t'.amplitude-current-minutes[amplitude-playlist-current-minutes=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-current-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-current-minutes[amplitude-main-current-minutes=\"true\"]',\n\t\t\t\t'.amplitude-current-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tGrabs the current minute selectors\n\t\t*/\n const currentMinuteSelectors = document.querySelectorAll( minuteSelectors.join() );\n\n\t\t/*\n\t\t\tSet the current minute selector's inner html to minutes passed in.\n\t\t*/\n\t\tfor( let i = 0, l = currentMinuteSelectors.length; i < l; i++ ){\n\t\t\t/*\n\t\t\t\tIf the selector is a main selector, we set the seconds.\n\t\t\t*/\n\t\t\tif( currentMinuteSelectors[i].getAttribute('amplitude-main-current-minutes') == 'true' ){\n\t\t\t\tcurrentMinuteSelectors[i].innerHTML = minutes;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& currentMinuteSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\tcurrentMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\tdoes not have a playlist then we set the minutes. This\n\t\t\t\t\tmeans that the current selector is an individual song\n\t\t\t\t\tselector.\n\t\t\t\t*/\n\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t&& !currentMinuteSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tcurrentMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t*/\n\t\t\t\t}else{\n\t\t\t\t\tcurrentMinuteSelectors[i].innerHTML = '00';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Resets the current minutes displays to 00\n\t *\n\t * @access public\n\t */\n\tfunction resetCurrentMinutes(){\n\t\t/*\n\t\t\tGets the minutes display elements\n\t\t*/\n\t\tlet minuteSelectors = document.querySelectorAll('.amplitude-current-minutes');\n\n\t\t/*\n\t\t\tIterates over all of the minute selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( let i = 0; i < minuteSelectors.length; i++ ){\n\t\t\tminuteSelectors[i].innerHTML = '00';\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the current seconds for the song.\n\t *\n\t * @access public\n\t * @param {number} seconds\t- An integer conaining how many seconds into the song.\n\t */\n\tfunction syncCurrentSeconds( seconds ){\n\t\t/*\n\t\t\tGets all of the song second selectors. If the active playlist\n\t\t\tis not null, then we get the playlist selectors.\n\t\t*/\n\t\tlet secondSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-current-seconds[amplitude-main-current-seconds=\"true\"]',\n\t\t\t\t'.amplitude-current-seconds[amplitude-playlist-current-seconds=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-current-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-current-seconds[amplitude-main-current-seconds=\"true\"]',\n\t\t\t\t'.amplitude-current-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n /*\n \tGet all of the second selectors\n */\n const currentSecondSelectors = document.querySelectorAll( secondSelectors.join() );\n\n /*\n \tIterate over all of the second selectors.\n */\n for( let i = 0, l = currentSecondSelectors.length; i < l; i++ ){\n \t/*\n \t\tIf the selector is a main selector, we set the seconds.\n \t*/\n \tif( currentSecondSelectors[i].getAttribute('amplitude-main-current-seconds') == 'true' ){\n \t\tcurrentSecondSelectors[i].innerHTML = seconds;\n \t}else{\n \t\t/*\n \t\t\tIf the active playlist is not null or empty\n \t\t\tand the attribute of the playlist is equal to the\n \t\t\tactive playlist, then we set the inner html.\n \t\t*/\n \t\tif( config.active_playlist != ''\n \t\t\t&& config.active_playlist != null\n \t\t\t&& currentSecondSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n \t\t\t\tcurrentSecondSelectors[i].innerHTML = seconds;\n \t\t/*\n \t\t\tIf the active playlist is not set and the selector\n \t\t\tdoes not have a playlist then we set the seconds. This\n \t\t\tmeans that the current selector is an individual song\n \t\t\tselector.\n \t\t*/\n \t\t}else if( config.active_playlist == ''\n \t\t\t|| config.active_playlist == null\n \t\t\t&& !currentSecondSelectors[i].hasAttribute('amplitude-playlist') ){\n \t\t\t\tcurrentSecondSelectors[i].innerHTML = seconds;\n \t\t/*\n \t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n \t\t*/\n \t\t}else{\n \t\t\tcurrentSecondSelectors[i].innerHTML = '00';\n \t\t}\n \t}\n }\n\t}\n\n\t/**\n\t * Resets the current seconds displays to 00\n\t *\n\t * @access public\n\t */\n\tfunction resetCurrentSeconds(){\n\t\t/*\n\t\t\tGets the seconds display elements\n\t\t*/\n\t\tlet secondSelectors = document.querySelectorAll('.amplitude-current-seconds');\n\n\t\t/*\n\t\t\tIterates over all of the seconds selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( let i = 0; i < secondSelectors.length; i++ ){\n\t\t\tsecondSelectors[i].innerHTML = '00';\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the current time for the song. This\n\t * is a computed field that will be commonly used.\n\t *\n\t * @access public\n\t * @param {object} currentTime \t- A json object conaining the parts for the current time for the song.\n\t */\n\tfunction syncCurrentTime( currentTime ){\n\t\t/*\n\t\t\tGets all of the song time selectors.\n\t\t*/\n\t\tlet timeSelectors = [\n\t\t\t'.amplitude-current-time[amplitude-main-current-time=\"true\"]',\n\t\t\t'.amplitude-current-time[amplitude-playlist-main-current-time=\"'+config.active_playlist+'\"]',\n\t\t\t'.amplitude-current-time[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t];\n\n\t\t/*\n\t\t\tGet all of the time selectors.\n\t\t*/\n\t\tlet currentTimeSelectors = document.querySelectorAll( timeSelectors.join() );\n\n\t\t/*\n\t\t\tSet the time selector's inner html to the current time for the song. The current\n\t\t\ttime is computed by joining minutes and seconds.\n\t\t*/\n\t\tvar timeText = currentTime.minutes+':'+currentTime.seconds;\n\t\tif ( currentTime.hours > 0 ) {\n\t\t\ttimeText = currentTime.hours + ':' + timeText;\n\t\t}\n\t\tfor( let i = 0, l=currentTimeSelectors.length; i < l; i++ ){\n\t\t\tcurrentTimeSelectors[i].innerHTML = timeText;\n\t\t}\n\n\t}\n\n\t/**\n\t * Resets the current time displays to 00:00\n\t *\n\t * @access public\n\t */\n\tfunction resetCurrentTime(){\n\t\t/*\n\t\t\tGets the time selector display elements\n\t\t*/\n\t\tlet timeSelectors = document.querySelectorAll('.amplitude-current-time');\n\n\t\t/*\n\t\t\tIterates over all of the time selectors and sets the inner HTML\n\t\t\tto 00.\n\t\t*/\n\t\tfor( let i = 0; i < timeSelectors.length; i++ ){\n\t\t\ttimeSelectors[i].innerHTML = '00:00';\n\t\t}\n\t}\n\n\t/**\n\t * Syncs the song played progress bars. These are HTML5 progress elements.\n\t *\n\t * @access private\n\t * @param {number} songPlayedPercentage \t- The percentage of the song that has been played.\n\t */\n\tfunction syncSongPlayedProgressBar( songPlayedPercentage ){\n\t\tsyncMainSongPlayedProgressBars( songPlayedPercentage );\n\t\tsyncPlaylistSongPlayedProgressBars( songPlayedPercentage );\n\t\tsyncIndividualSongPlayedProgressBars( songPlayedPercentage );\n\t}\n\n\t/**\n\t * Sync how much has been played with a progress bar. This is the main progress bar.\n\t *\n\t * @access private\n\t * @param {number} songPlayedPercentage \t- The percent of the song completed.\n\t */\n\tfunction syncMainSongPlayedProgressBars( songPlayedPercentage ){\n\t\t/*\n\t\t\tEnsure that the song completion percentage is a number\n\t\t*/\n\t\tif( !isNaN( songPlayedPercentage ) ){\n\t\t\t/*\n\t\t\t\tGet all of the song progress bars\n\t\t\t*/\n\t\t\tlet songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-main-song-played-progress=\"true\"]');\n\n\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\tlet max = songPlayedProgressBars[i].max;\n\n\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sync how much has been played with a progress bar. This is the playlist progress bar.\n\t *\n\t * @access public\n\t * @param {number} songPlayedPercentage \t- The percent of the song completed.\n\t */\n\tfunction syncPlaylistSongPlayedProgressBars( songPlayedPercentage ){\n\t\t/*\n\t\t\tEnsure that the song completion percentage is a number\n\t\t*/\n\t\tif( !isNaN( songPlayedPercentage ) ){\n\t\t\t/*\n\t\t\t\tGet all of the song progress bars\n\t\t\t*/\n\t\t\tlet songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-playlist-song-played-progress=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]');\n\n\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\tlet max = songPlayedProgressBars[i].max;\n\n\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sync how much has been played with a progress bar. This is for an individual song.\n\t *\n\t * @access private\n\t * @param {number} songPlayedPercentage \t- The percent of the song completed.\n\t */\n\tfunction syncIndividualSongPlayedProgressBars( songPlayedPercentage ){\n\t\t/*\n\t\t\tEnsure that the song completion percentage is a number\n\t\t*/\n\t\tif( !isNaN( songPlayedPercentage ) ){\n\t\t\t/*\n\t\t\t\tIf the active playlist is not null, we get the individual song\n\t\t\t\tplayed progress for the playlist.\n\t\t\t*/\n\t\t\tif( config.active_playlist != '' && config.active_playlist != null ){\n\t\t\t\t/*\n\t\t\t\t\tGet all of the song progress bars\n\t\t\t\t*/\n\t\t\t let songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-playlist=\"'+config.active_playlist+'\"][amplitude-song-index=\"'+config.active_index+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\t let max = songPlayedProgressBars[i].max;\n\n\t\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tGet all of the song progress bars\n\t\t\t\t*/\n\t\t\t\tlet songPlayedProgressBars = document.querySelectorAll('.amplitude-song-played-progress[amplitude-song-index=\"'+config.active_index+'\"]');\n\n\t\t\t\tfor( let i = 0; i < songPlayedProgressBars.length; i++ ){\n\t\t\t\t\tlet max = songPlayedProgressBars[i].max;\n\n\t\t\t\t\tsongPlayedProgressBars[i].value = ( songPlayedPercentage / 100 ) * max;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets an element to be playing by removing the 'amplitude-paused' class\n\t * and adding the 'amplitude-playing' class\n\t *\n\t * @access public\n\t * @param {element} element \t- The element getting the playing class added.\n\t */\n\tfunction setElementPlay( element ){\n\t\telement.classList.add('amplitude-playing');\n\t\telement.classList.remove('amplitude-paused');\n\t}\n\n\t/**\n\t * Sets an element to be paused by adding the 'amplitude-paused' class\n\t * and removing the 'amplitude-playing' class\n\t *\n\t * @access public\n\t * @param {element} element \t- The element getting the paused class added.\n\t */\n\tfunction setElementPause( element ){\n\t\telement.classList.remove('amplitude-playing');\n\t\telement.classList.add('amplitude-paused');\n\t}\n\n\t/**\n\t * Updates any elements that display the duration hour for the song.\n\t *\n\t * @access public\n\t * @param {number} hours \t\t- An integer conaining how many hours are in the song\n\t */\n\tfunction syncDurationHours( hours ){\n\t\t/*\n\t\t\tGets all of the song hour selectors.\n\t\t*/\n\t\tlet hourSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-duration-hours[amplitude-main-duration-hours=\"true\"]',\n\t\t\t\t'.amplitude-duration-hours[amplitude-playlist-duration-hours=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-duration-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\thourSelectors = [\n\t\t\t\t'.amplitude-duration-hours[amplitude-main-duration-hours=\"true\"]',\n\t\t\t\t'.amplitude-duration-hours[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tEnsures that there are some hour selectors.\n\t\t*/\n\t\tif( document.querySelectorAll( hourSelectors.join() ).length > 0 ){\n\t\t\t/*\n\t\t\t\tGet all of the hour selectors\n\t\t\t*/\n\t\t\tlet durationHourSelectors = document.querySelectorAll( hourSelectors.join() );\n\n\t\t\t/*\n\t\t\t\tSet the duration hour selector's inner html to hours passed in.\n\t\t\t*/\n\t\t\tfor( let i = 0; i < durationHourSelectors.length; i++ ){\n\t\t\t\t/*\n\t\t\t\t\tIf the selector is a main selector, we set the hours.\n\t\t\t\t*/\n\t\t\t\tif( durationHourSelectors[i].getAttribute('amplitude-main-duration-hours') == 'true' ){\n\t\t\t\t\tdurationHourSelectors[i].innerHTML = hours;\n\t\t\t\t}else{\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t\t*/\n\t\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t\t&& durationHourSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\t\tdurationHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\t\tdoes not have a playlist then we set the hours. This\n\t\t\t\t\t\tmeans that the duration selector is an individual song\n\t\t\t\t\t\tselector.\n\t\t\t\t\t*/\n\t\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t\t&& !durationHourSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\t\tdurationHourSelectors[i].innerHTML = hours;\n\t\t\t\t\t/*\n\t\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t\t*/\n\t\t\t\t\t}else{\n\t\t\t\t\t\tdurationHourSelectors[i].innerHTML = '0';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the duration minutes for the song.\n\t *\n\t * @access public\n\t * @param {number} minutes \t- An integer conaining how many minutes into the song.\n\t */\n\tfunction syncDurationMinutes( minutes ){\n\t\t/*\n\t\t\tGets all of the song minute selectors.\n\t\t*/\n\t\tlet minuteSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-duration-minutes[amplitude-main-duration-minutes=\"true\"]',\n\t\t\t\t'.amplitude-duration-minutes[amplitude-playlist-duration-minutes=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-duration-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tminuteSelectors = [\n\t\t\t\t'.amplitude-duration-minutes[amplitude-main-duration-minutes=\"true\"]',\n\t\t\t\t'.amplitude-duration-minutes[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tGet all of the minute selectors\n\t\t*/\n\t\tlet durationMinuteSelectors = document.querySelectorAll( minuteSelectors.join() );\n\n\t\t/*\n\t\t\tSet the duration minute selector's inner html to minutes passed in.\n\t\t*/\n\t\tfor( let i = 0; i < durationMinuteSelectors.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the selector is a main selector, we set the seconds.\n\t\t\t*/\n\t\t\tif( durationMinuteSelectors[i].getAttribute('amplitude-main-duration-minutes') == 'true' ){\n\t\t\t\tdurationMinuteSelectors[i].innerHTML = minutes;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& durationMinuteSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\tdurationMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\tdoes not have a playlist then we set the minutes. This\n\t\t\t\t\tmeans that the duration selector is an individual song\n\t\t\t\t\tselector.\n\t\t\t\t*/\n\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t&& !durationMinuteSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tdurationMinuteSelectors[i].innerHTML = minutes;\n\t\t\t\t/*\n\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t*/\n\t\t\t\t}else{\n\t\t\t\t\tdurationMinuteSelectors[i].innerHTML = '00';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates any elements that display the duration seconds for the song.\n\t *\n\t * @access private\n\t * @param {number} seconds \t- An integer conaining how many seconds into the song.\n\t */\n\tfunction syncDurationSeconds( seconds ){\n\t\t/*\n\t\t\tGets all of the song second selectors. If the active playlist\n\t\t\tis not null, then we get the playlist selectors.\n\t\t*/\n\t\tlet secondSelectors = [];\n\n\t\tif( config.active_playlist != null && config.active_playlist != '' ){\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-duration-seconds[amplitude-main-duration-seconds=\"true\"]',\n\t\t\t\t'.amplitude-duration-seconds[amplitude-playlist-duration-seconds=\"true\"][amplitude-playlist=\"'+config.active_playlist+'\"]',\n\t\t\t\t'.amplitude-duration-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}else{\n\t\t\tsecondSelectors = [\n\t\t\t\t'.amplitude-duration-seconds[amplitude-main-duration-seconds=\"true\"]',\n\t\t\t\t'.amplitude-duration-seconds[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t\t];\n\t\t}\n\n\t\t/*\n\t\t\tGet all of the second selectors\n\t\t*/\n\t\tlet durationSecondSelectors = document.querySelectorAll( secondSelectors.join() );\n\n\t\t/*\n\t\t\tIterate over all of the second selectors.\n\t\t*/\n\t\tfor( let i = 0; i < durationSecondSelectors.length; i++ ){\n\t\t\t/*\n\t\t\t\tIf the selector is a main selector, we set the seconds.\n\t\t\t*/\n\t\t\tif( durationSecondSelectors[i].getAttribute('amplitude-main-duration-seconds') == 'true' ){\n\t\t\t\tdurationSecondSelectors[i].innerHTML = seconds;\n\t\t\t}else{\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not null or empty\n\t\t\t\t\tand the attribute of the playlist is equal to the\n\t\t\t\t\tactive playlist, then we set the inner html.\n\t\t\t\t*/\n\t\t\t\tif( config.active_playlist != ''\n\t\t\t\t\t&& config.active_playlist != null\n\t\t\t\t\t&& durationSecondSelectors[i].getAttribute('amplitude-playlist') == config.active_playlist ){\n\t\t\t\t\t\tdurationSecondSelectors[i].innerHTML = seconds;\n\t\t\t\t/*\n\t\t\t\t\tIf the active playlist is not set and the selector\n\t\t\t\t\tdoes not have a playlist then we set the seconds. This\n\t\t\t\t\tmeans that the duration selector is an individual song\n\t\t\t\t\tselector.\n\t\t\t\t*/\n\t\t\t\t}else if( config.active_playlist == ''\n\t\t\t\t\t|| config.active_playlist == null\n\t\t\t\t\t&& !durationSecondSelectors[i].hasAttribute('amplitude-playlist') ){\n\t\t\t\t\t\tdurationSecondSelectors[i].innerHTML = seconds;\n\t\t\t\t/*\n\t\t\t\t\tIf nothing else matches, set the selector's inner HTML to '00'\n\t\t\t\t*/\n\t\t\t\t}else{\n\t\t\t\t\tdurationSecondSelectors[i].innerHTML = '00';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Updates any elements that display the duration time for the song. This\n\t * is a computed field that will be commonly used.\n\t *\n\t * @access public\n\t * @param {object} durationTime \t- A json object conaining the parts for the duration time for the song.\n\t */\n\tfunction syncDurationTime( durationTime ){\n\t\t/*\n\t\t\tGets all of the song time selectors.\n\t\t*/\n\t\tlet timeSelectors = [\n\t\t\t'.amplitude-duration-time[amplitude-main-duration-time=\"true\"]',\n\t\t\t'.amplitude-duration-time[amplitude-playlist-main-duration-time=\"'+config.active_playlist+'\"]',\n\t\t\t'.amplitude-duration-time[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t];\n\n\t\t/*\n\t\t\tGet all of the time selectors.\n\t\t*/\n\t\tlet durationTimeSelectors = document.querySelectorAll( timeSelectors.join() );\n\n\t\t/*\n\t\t\tSet the time selector's inner html to the duration time for the song. The duration\n\t\t\ttime is computed by joining minutes and seconds.\n\t\t*/\n\t\tvar durationText = '00:00';\n\t\tif( !isNaN( durationTime.minutes ) && !isNaN( durationTime.seconds ) ){\n\t\t\tdurationText = durationTime.minutes+':'+durationTime.seconds;\n\t\t\tif( !isNaN( durationTime.hours ) && durationTime.hours > 0 ){\n\t\t\t\tdurationText = durationTime.hours+':'+durationText;\n\t\t\t}\n\t\t}\n\t\tfor( var i = 0; i < durationTimeSelectors.length; i++ ){\n\t\t\tdurationTimeSelectors[i].innerHTML = durationText;\n\t\t}\n\n\t}\n\n\t/**\n\t * Updates the elements that show how much time is remaining in the song.\n\t *\n\t * @access public\n\t * @param {object} currentTime \t- A json object containing the parts for the current time for the song.\n\t * @param {object} durationTime - A json object conaining the parts for the duration time for the song.\n\t */\n\tfunction syncCountDownTime( currentTime, songDuration ){\n\t\t/*\n\t\t\tInitialize time remaining.\n\t\t*/\n\t\tlet timeRemaining = '00:00';\n\n\t\t/*\n\t\t\tEnsure that all values are defined.\n\t\t*/\n\t\tif( currentTime != undefined && songDuration != undefined ){\n\t\t\t/*\n\t\t\t\tInitialize the total current seconds and total duration seconds\n\t\t\t*/\n\t\t\tlet totalCurrentSeconds = parseInt( currentTime.seconds ) + ( parseInt( currentTime.minutes ) * 60 ) + ( ( parseInt( currentTime.hours ) * 60 * 60 ) );\n\t\t\tlet totalDurationSeconds = parseInt( songDuration.seconds ) + ( parseInt( songDuration.minutes ) * 60 ) + ( ( parseInt( songDuration.hours ) * 60 * 60 ) );\n\n\t\t\t/*\n\t\t\t\tIf the two variables are numbers we continue the computing.\n\t\t\t*/\n\t\t\tif( !isNaN( totalCurrentSeconds ) && !isNaN( totalDurationSeconds ) ){\n\t\t\t\t/*\n\t\t\t\t\tFind the total remaining seconds.\n\t\t\t\t*/\n\t\t\t\tlet timeRemainingTotalSeconds = totalDurationSeconds - totalCurrentSeconds;\n\n\t\t\t\tvar remainingHours = Math.floor(timeRemainingTotalSeconds / 3600);\n\t\t\t\tvar remainingMinutes = Math.floor((timeRemainingTotalSeconds - (remainingHours * 3600)) / 60);\n\t\t\t\tvar remainingSeconds = timeRemainingTotalSeconds - (remainingHours * 3600) - (remainingMinutes * 60);\n\n\t\t\t\ttimeRemaining = (remainingMinutes < 10 ? '0' + remainingMinutes : remainingMinutes) + ':' +\n\t\t\t\t\t(remainingSeconds < 10 ? '0' + remainingSeconds : remainingSeconds);\n\n\t\t\t\tif(remainingHours > 0) {\n\t\t\t\t\ttimeRemaining = remainingHours + ':' + timeRemaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\tGets all of the song time selectors.\n\t\t*/\n\t let timeSelectors = [\n\t\t\t'.amplitude-time-remaining[amplitude-main-time-remaining=\"true\"]',\n\t\t\t'.amplitude-time-remaining[amplitude-playlist-main-time-remaining=\"'+config.active_playlist+'\"]',\n\t\t\t'.amplitude-time-remaining[amplitude-song-index=\"'+config.active_index+'\"]'\n\t\t];\n\n\t\t/*\n\t\t\tGet all of the time selectors.\n\t\t*/\n\t let timeRemainingSelectors = document.querySelectorAll( timeSelectors.join() );\n\n\t\t/*\n\t\t\tSet the time selector's inner html to the duration time for the song. The duration\n\t\t\ttime is computed by joining minutes and seconds.\n\t\t*/\n\t\tfor( let i = 0; i < timeRemainingSelectors.length; i++ ){\n\t\t\ttimeRemainingSelectors[i].innerHTML = timeRemaining;\n\t\t}\n\t}\n\n\t/*\n\t\tReturn the publically available functions.\n\t*/\n\treturn {\n\t\tsyncCurrentHours: syncCurrentHours,\n\t\tsyncCurrentMinutes: syncCurrentMinutes,\n\t\tsyncCurrentSeconds: syncCurrentSeconds,\n\t\tsyncCurrentTime: syncCurrentTime,\n\t\tresetCurrentHours: resetCurrentHours,\n\t\tresetCurrentMinutes: resetCurrentMinutes,\n\t\tresetCurrentSeconds: resetCurrentSeconds,\n\t\tresetCurrentTime: resetCurrentTime,\n\t\tsyncSongPlayedProgressBar: syncSongPlayedProgressBar,\n\t\tsetElementPlay: setElementPlay,\n\t\tsetElementPause: setElementPause,\n\t\tsyncDurationHours: syncDurationHours,\n\t\tsyncDurationMinutes: syncDurationMinutes,\n\t\tsyncDurationSeconds: syncDurationSeconds,\n\t\tsyncDurationTime: syncDurationTime,\n\t\tsyncCountDownTime: syncCountDownTime\n\t}\n})();\n\nexport default AmplitudeVisualSyncHelpers\n\n\n\n// WEBPACK FOOTER //\n// ./src/visual/helpers.js"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/amplitude.min.js b/dist/amplitude.min.js index b20e26f1..257d3b4f 100644 --- a/dist/amplitude.min.js +++ b/dist/amplitude.min.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Amplitude",[],t):"object"==typeof exports?exports.Amplitude=t():e.Amplitude=t()}(this,function(){return function(e){function t(l){if(a[l])return a[l].exports;var u=a[l]={i:l,l:!1,exports:{}};return e[l].call(u.exports,u,u.exports,t),u.l=!0,u.exports}var a={};return t.m=e,t.c=a,t.i=function(e){return e},t.d=function(e,a,l){t.o(e,a)||Object.defineProperty(e,a,{configurable:!1,enumerable:!0,get:l})},t.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(a,"a",a),a},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=8)}([function(e,t,a){"use strict";e.exports={version:"3.3.0",active_song:new Audio,active_metadata:{},active_album:"",active_index:0,active_playlist:"",autoplay:!1,playback_speed:1,callbacks:{},songs:[],playlists:{},start_song:"",shuffled_playlists:{},starting_playlist:"",starting_playlist_song:"",shuffled_statuses:{},shuffled_active_indexes:{},repeat_statuses:{},repeat:!1,repeat_song:!1,shuffle_list:{},shuffle_on:!1,shuffle_active_index:0,default_album_art:"",debug:!1,volume:.5,pre_mute_volume:.5,volume_increment:5,volume_decrement:5,soundcloud_client:"",soundcloud_use_art:!1,soundcloud_song_count:0,soundcloud_songs_ready:0,is_touch_moving:!1,buffered:0,bindings:{},continue_next:!0}},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(3),s=l(n),d=a(2),o=l(d),f=function(){function e(){i.default.active_song=new Audio,i.default.active_metadata={},i.default.active_album="",i.default.active_index=0,i.default.active_playlist="",i.default.active_playlist="",i.default.autoplay=!1,i.default.playback_speed=1,i.default.callbacks={},i.default.songs=[],i.default.playlists={},i.default.start_song="",i.default.shuffled_playlists={},i.default.starting_playlist="",i.default.starting_playlist_song="",i.default.shuffled_statuses={},i.default.repeat=!1,i.default.shuffle_list={},i.default.shuffle_on=!1,i.default.shuffle_active_index=0,i.default.default_album_art="",i.default.debug=!1,i.default.handle_song_elements=!0,i.default.volume=.5,i.default.pre_mute_volume=.5,i.default.volume_increment=5,i.default.volume_decrement=5,i.default.soundcloud_client="",i.default.soundcloud_use_art=!1,i.default.soundcloud_song_count=0,i.default.soundcloud_songs_ready=0,i.default.continue_next=!0}function t(e){i.default.debug&&console.log(e)}function a(e){if(i.default.callbacks[e]){var a=i.default.callbacks[e];t("Running Callback: "+e);try{a()}catch(e){if("CANCEL EVENT"==e.message)throw e;t("Callback error: "+e.message)}}}function l(e){var t=i.default.songs[e];s.default.stop(),o.default.setPlayPauseButtonsToPause(),o.default.resetSongSliders(),o.default.resetSongPlayedProgressBars(),o.default.resetTimes(),n(t)&&a("album_change"),f(t,e),o.default.displaySongMetadata(),o.default.setActiveContainer(),o.default.syncSongDuration(),a("song_change")}function u(e){return e!=i.default.active_index}function n(e){return i.default.active_album!=e}function d(e){return i.default.active_playlist!=e}function f(e,t){i.default.active_song.src=e.url,i.default.active_metadata=e,i.default.active_album=e.album,i.default.active_index=t}function r(){for(var e=new Array(i.default.songs.length),t=0;t0;a--){p(e,a,Math.floor(Math.random()*i.default.songs.length+1)-1)}i.default.shuffle_list=e}function c(e){for(var t=new Array(i.default.playlists[e].length),a=0;a0;l--){p(t,l,Math.floor(Math.random()*i.default.playlists[e].length+1)-1)}i.default.shuffled_playlists[e]=t}function p(e,t,a){var l=e[t];e[t]=e[a],e[a]=l}function y(e){i.default.active_playlist!=e&&a("playlist_changed"),i.default.active_playlist=e}function v(e){return/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.test(e)}function g(e){return!isNaN(e)&&parseInt(Number(e))==e&&!isNaN(parseInt(e,10))}return{resetConfig:e,writeDebugMessage:t,runCallback:a,changeSong:l,checkNewSong:u,checkNewAlbum:n,checkNewPlaylist:d,shuffleSongs:r,shufflePlaylistSongs:c,setActivePlaylist:y,isURL:v,isInt:g}}();t.default=f,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(10),s=l(n),d=function(){function e(e,t){s.default.syncCurrentHours(e.hours),s.default.syncCurrentMinutes(e.minutes),s.default.syncCurrentSeconds(e.seconds),s.default.syncCurrentTime(e),x(t),A(i.default.active_playlist,t),L(i.default.active_playlist,i.default.active_index,t),s.default.syncSongPlayedProgressBar(t)}function t(){s.default.resetCurrentHours(),s.default.resetCurrentMinutes(),s.default.resetCurrentSeconds(),s.default.resetCurrentTime()}function a(){for(var e=document.getElementsByClassName("amplitude-song-slider"),t=0;t=0?t[a].setAttribute("src",i.default.active_metadata[l]):t[a].innerHTML=i.default.active_metadata[l]:e.indexOf(l)>=0?""!=i.default.default_album_art?t[a].setAttribute("src",i.default.default_album_art):t[a].setAttribute("src",""):t[a].innerHTML="")}}function o(e,t){for(var a=["cover_art_url","station_art_url","podcast_episode_cover_art_url"],l=document.querySelectorAll('[amplitude-song-info][amplitude-playlist="'+t+'"]'),u=0;u=0?l[u].setAttribute("src",e[i]):l[u].innerHTML=e[i]:a.indexOf(i)>=0?""!=e.default_album_art?l[u].setAttribute("src",e.default_album_art):l[u].setAttribute("src",""):l[u].innerHTML="")}}function f(){for(var e=document.getElementsByClassName("amplitude-playback-speed"),t=0;t=0?t[a].setAttribute("src",i.default.songs[u][l]):t[a].innerHTML=i.default.songs[u][l])}}return{syncCurrentTime:e,resetTimes:t,resetSongSliders:a,resetSongPlayedProgressBars:u,resetSongBufferedProgressBars:l,setActiveContainer:n,displaySongMetadata:d,syncPlaybackSpeed:f,syncBufferedProgressBars:r,syncVolumeSliders:c,setPlayPauseButtonsToPause:p,setFirstSongInPlaylist:o,syncMainPlayPause:y,syncPlaylistPlayPause:v,syncSongPlayPause:g,syncRepeat:m,syncRepeatSong:h,syncRepeatPlaylist:_,syncMute:P,syncShuffle:b,syncPlaylistShuffle:S,syncMainSliderLocation:x,syncPlaylistSliderLocation:A,syncSongSliderLocation:L,syncVolumeSliderLocation:M,syncSongDuration:k,syncSongsMetaData:E}}();t.default=d,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(1),s=l(n),d=a(2),o=l(d),f=function(){function e(){s.default.runCallback("before_play"),i.default.active_metadata.live&&f(),/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)&&!i.default.paused&&f(),i.default.active_song.play(),i.default.active_song.playbackRate=i.default.playback_speed,s.default.runCallback("after_play")}function t(){s.default.runCallback("before_pause"),i.default.active_song.pause(),i.default.paused=!0,i.default.active_metadata.live&&d(),s.default.runCallback("after_pause")}function a(){s.default.runCallback("before_stop"),0!=i.default.active_song.currentTime&&(i.default.active_song.currentTime=0),i.default.active_song.pause(),i.default.active_metadata.live&&d(),s.default.runCallback("after_stop")}function l(e){0==e?o.default.syncMute(!0):o.default.syncMute(!1),i.default.active_song.volume=e/100}function u(e){i.default.active_metadata.live||(i.default.active_song.currentTime=i.default.active_song.duration*(song_percentage/100))}function n(e){i.default.active_song.addEventListener("canplaythrough",function(){i.default.active_song.duration>=e&&e>0?i.default.active_song.currentTime=e:s.default.writeDebugMessage("Amplitude can't skip to a location greater than the duration of the audio or less than 0")},{once:!0})}function d(){i.default.active_song.src="",i.default.active_song.load()}function f(){i.default.active_song.src=i.default.active_metadata.url,i.default.active_song.load()}function r(t){t.url?(i.default.active_song.src=t.url,i.default.active_metadata=t,i.default.active_album=t.album):s.default.writeDebugMessage("The song needs to have a URL!"),o.default.syncMainPlayPause("playing"),o.default.displaySongMetadata(),o.default.resetSongSliders(),o.default.resetSongPlayedProgressBars(),o.default.resetTimes(),e()}function c(t){a(),s.default.checkNewPlaylist(null)&&(s.default.setActivePlaylist(null),s.default.changeSong(t)),s.default.checkNewSong(t)&&s.default.changeSong(t),o.default.syncMainPlayPause("playing"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),e()}function p(t,l){a();var u=i.default.playlists[l][t];s.default.checkNewPlaylist(l)&&(s.default.setActivePlaylist(l),s.default.changeSong(u)),s.default.checkNewSong(u)&&s.default.changeSong(u),o.default.syncMainPlayPause("playing"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),e()}function y(e){i.default.playback_speed=e,i.default.active_song.playbackRate=i.default.playback_speed}return{play:e,pause:t,stop:a,setVolume:l,setSongLocation:u,skipToLocation:n,disconnectStream:d,reconnectStream:f,playNow:r,playSongAtIndex:c,playPlaylistSongAtIndex:p,setPlaybackSpeed:y}}();t.default=f,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(1),s=l(n),d=a(7),o=l(d),f=function(){function e(){s.default.writeDebugMessage("Beginning initialization of event handlers.."),document.addEventListener("touchmove",function(){i.default.is_touch_moving=!0}),document.addEventListener("touchend",function(){i.default.is_touch_moving&&(i.default.is_touch_moving=!1)}),t(),a(),l(),u(),n(),d(),f(),r(),c(),p(),y(),v(),g(),m(),_(),h(),P(),b(),S()}function t(){i.default.active_song.removeEventListener("timeupdate",o.default.updateTime),i.default.active_song.addEventListener("timeupdate",o.default.updateTime),i.default.active_song.removeEventListener("durationchange",o.default.updateTime),i.default.active_song.addEventListener("durationchange",o.default.updateTime)}function a(){document.removeEventListener("keydown",s.default.keydown),document.addEventListener("keydown",o.default.keydown)}function l(){i.default.active_song.removeEventListener("ended",o.default.songEnded),i.default.active_song.addEventListener("ended",o.default.songEnded)}function u(){i.default.active_song.removeEventListener("progress",o.default.progess),i.default.active_song.addEventListener("progress",o.default.progress)}function n(){for(var e=document.getElementsByClassName("amplitude-play"),t=0;t0||navigator.userAgent.match(/Trident.*rv\:11\./)?(a[l].removeEventListener("change",o.default.songSlider),a[l].addEventListener("change",o.default.songSlider)):(a[l].removeEventListener("input",o.default.songSlider),a[l].addEventListener("input",o.default.songSlider))}function g(){for(var e=window.navigator.userAgent,t=e.indexOf("MSIE "),a=document.getElementsByClassName("amplitude-volume-slider"),l=0;l0||navigator.userAgent.match(/Trident.*rv\:11\./)?(a[l].removeEventListener("change",o.default.volumeSlider),a[l].addEventListener("change",o.default.volumeSlider)):(a[l].removeEventListener("input",o.default.volumeSlider),a[l].addEventListener("input",o.default.volumeSlider))}function m(){for(var e=document.getElementsByClassName("amplitude-next"),t=0;t=60&&(l=Math.floor(a/60),(a%=60)<10&&(a="0"+a)),e.seconds=t,e.minutes=a,e.hours=l,e}function t(){var e={},t=(Math.floor(i.default.active_song.duration%60)<10?"0":"")+Math.floor(i.default.active_song.duration%60),a=Math.floor(i.default.active_song.duration/60),l="0";return a<10&&(a="0"+a),a>=60&&(l=Math.floor(a/60),(a%=60)<10&&(a="0"+a)),e.seconds=t,e.minutes=a,e.hours=l,e}function a(){return i.default.active_song.currentTime/i.default.active_song.duration*100}function l(e){o.default.setPlaybackSpeed(e)}function u(e,t){null==t?(i.default.repeat=e,s.default.syncRepeat()):(i.default.repeat_statuses[t]=e,s.default.syncRepeatPlaylist(t))}function n(e){i.default.repeat_song=e}function d(){i.default.active_song.paused?(s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),o.default.play()):(s.default.syncMainPlayPause("paused"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),o.default.pause())}function f(e){r.default.checkNewPlaylist(e)&&(r.default.setActivePlaylist(e),i.default.shuffled_statuses[e]?r.default.changeSong(i.default.shuffled_playlists[e][0].original_index):r.default.changeSong(i.default.playlists[e][0])),i.default.active_song.paused?(s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),o.default.play()):(s.default.syncMainPlayPause("paused"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),o.default.pause())}function p(e,t){r.default.checkNewPlaylist(e)&&(r.default.setActivePlaylist(e),r.default.changeSong(t)),r.default.checkNewSong(t)&&r.default.changeSong(t),i.default.active_song.paused?(s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),o.default.play()):(s.default.syncMainPlayPause("paused"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),o.default.pause())}function y(e){null==e?(i.default.shuffle_on?(i.default.shuffle_on=!1,i.default.shuffle_list={}):(i.default.shuffle_on=!0,r.default.shuffleSongs()),s.default.syncShuffle(i.default.shuffle_on)):(i.default.shuffled_statuses[e]?(i.default.shuffled_statuses[e]=!1,i.default.shuffled_playlists[e]=[]):(i.default.shuffled_statuses[e]=!0,r.default.shufflePlaylistSongs(e)),s.default.syncPlaylistShuffle(i.default.shuffled_statuses[e],e))}function v(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=0,a=!1;i.default.repeat_song?t=i.default.shuffle_on?i.default.shuffle_active_index:i.default.active_index:i.default.shuffle_on?parseInt(i.default.shuffle_active_index)+11&&void 0!==arguments[1]&&arguments[1],a=0,l=!1;if(i.default.repeat_song)a=i.default.shuffled_statuses[e]?i.default.shuffled_playlists[e][i.default.shuffled_active_indexes[e]].original_index:i.default.active_index;else if(i.default.shuffled_statuses[e]){var u=parseInt(i.default.shuffled_active_indexes[e]);u+1=0?(i.default.shuffle_active_index=parseInt(i.default.shuffle_active_index)-1,e=i.default.shuffle_list[parseInt(i.default.shuffle_active_index)].original_index):(i.default.shuffle_active_index=i.default.shuffle_list.length-1,e=i.default.shuffle_list[parseInt(i.default.shuffle_list.length)-1].original_index):(parseInt(i.default.active_index)-1>=0?i.default.active_index=parseInt(i.default.active_index)-1:i.default.active_index=i.default.songs.length-1,e=i.default.active_index),o.default.stop(),r.default.changeSong(e),o.default.play(),s.default.syncMainPlayPause("playing"),s.default.syncSongPlayPause(null,e,"playing"),r.default.runCallback("after_prev")}function _(e){var t=0;if(i.default.shuffled_statuses[e]){var a=parseInt(i.default.shuffled_active_indexes[e]);a-1>=0?(i.default.shuffled_active_indexes[e]=a-1,t=i.default.shuffled_playlists[e][i.default.shuffled_active_indexes[e]].original_index):(i.default.shuffled_active_indexes[e]=i.default.shuffled_playlists[e].length-1,t=i.default.shuffled_playlists[e][i.default.shuffled_playlists[e].length-1].original_index)}else{var l=i.default.playlists[e].indexOf(parseInt(i.default.active_index));i.default.active_index=l-1>=0?parseInt(i.default.playlists[e][l-1]):parseInt(i.default.playlists[e][i.default.playlists[e].length-1]),t=i.default.active_index}o.default.stop(),r.default.changeSong(t),r.default.setActivePlaylist(e),o.default.play(),s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(e,"playing"),s.default.syncSongPlayPause(e,t,"playing"),r.default.runCallback("after_prev")}function h(e){if(void 0!=i.default.bindings[e])switch(i.default.bindings[e]){case"play_pause":p(i.default.active_playlist,i.default.active_index);break;case"next":""==i.default.active_playlist||null==i.default.active_playlist?v():g(i.default.active_playlist);break;case"prev":""==i.default.active_playlist||null==i.default.active_playlist?c.setPrev():c.setPrevPlaylist(i.default.active_playlist);break;case"stop":s.default.setPlayPauseButtonsToPause(),o.default.stop();break;case"shuffle":""==i.default.active_playlist||null==i.default.active_playlist?AmplitudesEventHelpers.setShuffle(null):AmplitudeEvenstHelpers.setShuffle(i.default.active_playlist);break;case"repeat":c.setRepeat(!i.default.repeat),s.default.syncRepeat()}}return{computeCurrentTimes:e,computeSongDuration:t,computeSongCompletionPercentage:a,setPlaybackSpeed:l,setRepeat:u,setRepeatSong:n,setMainPlayPause:d,setPlaylistPlayPause:f,setSongPlayPause:p,setShuffle:y,setNext:v,setNextPlaylist:g,setPrev:m,setPrevPlaylist:_,runKeyEvent:h}}();t.default=c,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=a(0),n=l(i),s=a(3),d=l(s),o=a(1),f=l(o),r=a(4),c=l(r),p=a(9),y=l(p),v=a(2),g=l(v),m=function(){function e(e){var t=!1;if(f.default.resetConfig(),c.default.initializeEvents(),n.default.debug=void 0!=e.debug&&e.debug,e.songs?0!=e.songs.length?(n.default.songs=e.songs,t=!0):f.default.writeDebugMessage("Please add some songs, to your songs object!"):f.default.writeDebugMessage("Please provide a songs object for AmplitudeJS to run!"),e.playlists&&l(e.playlists)>0&&(n.default.playlists=e.playlists,m(),i(),s(),o(),r(),p(),v()),t){n.default.soundcloud_client=void 0!=e.soundcloud_client?e.soundcloud_client:"",n.default.soundcloud_use_art=void 0!=e.soundcloud_use_art?e.soundcloud_use_art:"";var u={};""!=n.default.soundcloud_client?(u=e,y.default.loadSoundCloud(u)):a(e)}f.default.writeDebugMessage("Initialized With: "),f.default.writeDebugMessage(n.default)}function t(){c.default.initializeEvents(),g.default.displaySongMetadata()}function a(e){void 0!=e.start_song?f.default.isInt(e.start_song)?f.default.changeSong(e.start_song):f.default.writeDebugMessage("You must enter an integer index for the start song."):f.default.changeSong(0),void 0!=e.shuffle_on&&e.shuffle_on&&(n.default.shuffle_on=!0,f.default.shuffleSongs(),g.default.syncShuffle(n.default.shuffle_on),f.default.changeSong(n.default.shuffle_list[0].original_index)),n.default.continue_next=void 0==e.continue_next||e.continue_next,n.default.playback_speed=void 0!=e.playback_speed?e.playback_speed:1,d.default.setPlaybackSpeed(n.default.playback_speed),n.default.active_song.preload=void 0!=e.preload?e.preload:"auto",n.default.callbacks=void 0!=e.callbacks?e.callbacks:{},n.default.bindings=void 0!=e.bindings?e.bindings:{},n.default.volume=void 0!=e.volume?e.volume:50,n.default.volume_increment=void 0!=e.volume_increment?e.volume_increment:5,n.default.volume_decrement=void 0!=e.volume_decrement?e.volume_decrement:5,d.default.setVolume(n.default.volume),g.default.syncVolumeSliders(),void 0!=e.default_album_art?n.default.default_album_art=e.default_album_art:n.default.default_album_art="",g.default.resetTimes(),g.default.setPlayPauseButtonsToPause(),g.default.syncSongsMetaData(),e.autoplay&&(""==e.starting_playlist?n.default.active_playlist=null:n.default.active_playlist=e.starting_playlist,g.default.syncMainPlayPause("playing"),g.default.syncSongPlayPause(n.default.active_playlist,0,"playing"),d.default.play()),void 0!=e.starting_playlist&&""!=e.starting_playlist&&(n.default.active_playlist=e.starting_playlist,void 0!=e.starting_playlist_song&&""!=e.starting_playlist_song?void 0!=u(e.playlists[e.starting_playlist][parseInt(e.starting_playlist_song)])?f.default.changeSong(e.playlists[e.starting_playlist][parseInt(e.starting_playlist_song)]):(f.default.changeSong(e.playlists[e.starting_playlist][0]),f.default.writeDebugMessage("The index of "+e.starting_playlist_song+" does not exist in the playlist "+e.starting_playlist)):f.default.changeSong(e.playlists[e.starting_playlist][0]),g.default.syncMainPlayPause("paused"),g.default.syncSongPlayPause(n.default.active_playlist,0,"paused")),f.default.runCallback("after_init")}function l(e){var t=0,a=void 0;for(a in e)e.hasOwnProperty(a)&&t++;return f.default.writeDebugMessage("You have "+t+" playlist(s) in your config"),t}function i(){for(var e in n.default.playlists)if(n.default.playlists.hasOwnProperty(e)&&n.default.playlists[e].songs)for(var t=0;t=0){var e=i.default.active_song.buffered.end(i.default.active_song.buffered.length-1),t=i.default.active_song.duration;i.default.buffered=e/t*100}if(o.default.syncBufferedProgressBars(),!i.default.active_metadata.live){var a=s.default.computeCurrentTimes(),l=s.default.computeSongCompletionPercentage(),u=s.default.computeSongDuration();o.default.syncCurrentTime(a,l),o.default.syncSongDuration(a,u),p.default.runCallback("time_update")}},keydown:function(e){s.default.runKeyEvent(e.which)},songEnded:function(){i.default.continue_next?""==i.default.active_playlist||null==i.default.active_playlist?s.default.setNext(!0):s.default.setNextPlaylist(i.default.active_playlist,!0):i.default.is_touch_moving||(o.default.setPlayPauseButtonsToPause(),r.default.stop())},progress:function(){if(i.default.active_song.buffered.length-1>=0){var e=i.default.active_song.buffered.end(i.default.active_song.buffered.length-1),t=i.default.active_song.duration;i.default.buffered=e/t*100}o.default.syncBufferedProgressBars()},play:function(){if(!i.default.is_touch_moving){var e=this.getAttribute("amplitude-song-index"),t=this.getAttribute("amplitude-playlist");null==t&&null==e&&s.default.setSongPlayPause(i.default.active_playlist,i.default.active_index),null!=t&&""!=t&&(p.default.checkNewPlaylist(t)?(p.default.setActivePlaylist(t),null!=e?(p.default.changeSong(e),s.default.setPlaylistPlayPause(t)):(p.default.changeSong(i.default.playlists[t][0]),s.default.setPlaylistPlayPause(t))):null!=e?(p.default.changeSong(e),s.default.setPlaylistPlayPause(t)):(p.default.changeSong(i.default.active_index),s.default.setPlaylistPlayPause(t))),null!=t&&""!=t||null==e||""==e||((p.default.checkNewSong(e)||i.default.active_playlist!=t)&&p.default.changeSong(e),s.default.setSongPlayPause(t,e))}},pause:function(){if(!i.default.is_touch_moving){var e=this.getAttribute("amplitude-song-index"),t=this.getAttribute("amplitude-playlist");null==e&&null==t&&(s.default.setSongPlayPause(i.default.active_playlist,i.default.active_index),r.default.pause()),(null!=t||""!=t&&i.default.active_playlist==t)&&(o.default.syncMainPlayPause("paused"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),r.default.pause()),null!=t&&""!=t||e!=i.default.active_index||(o.default.syncMainPlayPause("paused"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),r.default.pause())}},playPause:function(){if(!i.default.is_touch_moving)if(null!=this.getAttribute("amplitude-main-play-pause"))s.default.setMainPlayPause();else if(null!=this.getAttribute("amplitude-playlist-main-play-pause")){var e=this.getAttribute("amplitude-playlist");s.default.setPlaylistPlayPause(e)}else{var t=this.getAttribute("amplitude-playlist"),a=this.getAttribute("amplitude-song-index");s.default.setSongPlayPause(t,a)}},stop:function(){i.default.is_touch_moving||(o.default.setPlayPauseButtonsToPause(),r.default.stop())},mute:function(){i.default.is_touch_moving||(0==i.default.volume?(i.default.active_song.muted=!1,i.default.volume=i.default.pre_mute_volume,o.default.syncMute(!1)):(i.default.active_song.muted=!0,i.default.pre_mute_volume=i.default.volume,i.default.volume=0,o.default.syncMute(!0)),r.default.setVolume(i.default.volume),o.default.syncVolumeSliders(i.default.volume))},volumeUp:function(){i.default.is_touch_moving||(i.default.volume+i.default.volume_increment<=100?i.default.volume=i.default.volume+i.default.volume_increment:i.default.volume=100,r.default.setVolume(i.default.volume),o.default.syncVolumeSliders(i.default.volume))},volumeDown:function(){i.default.is_touch_moving||(i.default.volume-i.default.volume_increment>0?i.default.volume=i.default.volume-i.default.volume_increment:i.default.volume=0,r.default.setVolume(i.default.volume),o.default.syncVolumeSliders(i.default.volume))},songSlider:function(){var e=this.value;if(null!=this.getAttribute("amplitude-main-song-slider")){if(!i.default.active_metadata.live){var t=i.default.active_song.duration*(e/100);isFinite(t)&&(i.default.active_song.currentTime=t)}o.default.syncMainSliderLocation(e),""!=i.default.active_playlist&&null!=i.default.active_playlist&&o.default.syncPlaylistSliderLocation(i.default.active_playlist,e)}if(null!=this.getAttribute("amplitude-playlist-song-slider")){var a=this.getAttribute("amplitude-playlist");i.default.active_playlist==a&&(i.default.active_metadata.live||(i.default.active_song.currentTime=i.default.active_song.duration*(e/100)),o.default.syncMainSliderLocation(e),o.default.syncPlaylistSliderLocation(a,e))}if(null==this.getAttribute("amplitude-playlist-song-slider")&&null==this.getAttribute("amplitude-main-song-slider")){var l=this.getAttribute("amplitude-playlist"),u=this.getAttribute("amplitude-song-index");i.default.active_index==u&&(i.default.active_metadata.live||(i.default.active_song.currentTime=i.default.active_song.duration*(e/100)),o.default.syncMainSliderLocation(),""!=i.default.active_playlist&&null!=i.default.active_playlist&&i.default.active_playlist==l&&o.default.syncPlaylistSliderLocation(l,location),o.default.syncSongSliderLocation(l,u,location))}},volumeSlider:function(){r.default.setVolume(this.value),o.default.syncVolumeSliderLocation(this.value)},next:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))""==i.default.active_playlist||null==i.default.active_playlist?s.default.setNext():s.default.setNextPlaylist(i.default.active_playlist);else{var e=this.getAttribute("amplitude-playlist");s.default.setNextPlaylist(e)}},prev:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))""==i.default.active_playlist||null==i.default.active_playlist?s.default.setPrev():s.default.setPrevPlaylist(i.default.active_playlist);else{var e=this.getAttribute("amplitude-playlist");s.default.setPrevPlaylist(e)}},shuffle:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))s.default.setShuffle(null);else{var e=this.getAttribute("amplitude-playlist");s.default.setShuffle(e)}},repeat:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))s.default.setRepeat(!i.default.repeat,null);else{var e=this.getAttribute("amplitude-playlist");s.default.setRepeat(!i.default.repeat_statuses[e],e)}},repeatSong:function(){i.default.is_touch_moving||(s.default.setRepeatSong(!i.default.repeat_song),o.default.syncRepeatSong())},playbackSpeed:function(){if(!i.default.is_touch_moving){switch(i.default.playback_speed){case 1:s.default.setPlaybackSpeed(1.5);break;case 1.5:s.default.setPlaybackSpeed(2);break;case 2:s.default.setPlaybackSpeed(1)}o.default.syncPlaybackSpeed()}},skipTo:function(){if(!i.default.is_touch_moving)if(this.hasAttribute("amplitude-playlist")){var e=this.getAttribute("amplitude-playlist");p.default.checkNewPlaylist(e)&&p.default.setActivePlaylist(e);var t=parseInt(this.getAttribute("amplitude-location")),a=parseInt(this.getAttribute("amplitude-song-index"));p.default.changeSong(a),r.default.play(),o.default.syncMainPlayPause("playing"),o.default.syncPlaylistPlayPause(e,"playing"),o.default.syncSongPlayPause(e,a,"playing"),r.default.skipToLocation(t)}else{var l=parseInt(this.getAttribute("amplitude-location")),u=parseInt(this.getAttribute("amplitude-song-index"));p.default.changeSong(u),r.default.play(),o.default.syncMainPlayPause("playing"),o.default.syncSongPlayPause(null,u,"playing"),r.default.skipToLocation(l)}}},e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(6),i=l(u),n=a(3),s=l(n),d=a(1),o=l(d),f=a(4),r=(l(f),a(5)),c=l(r),p=a(2),y=l(p),v=a(0),g=l(v),m=function(){function e(e){i.default.initialize(e)}function t(){i.default.rebindDisplay()}function a(){return g.default.active_playlist}function l(){return g.default.playback_speed}function u(){return g.default.repeat}function n(){return g.default.shuffle_on}function d(e){return g.default.shuffled_statuses[e]}function f(){c.default.setShuffle(null)}function r(e){c.default.setShuffle(e)}function p(){g.default.is_touch_moving||(c.default.setRepeat(!g.default.repeat),y.default.syncRepeat())}function v(){g.default.is_touch_moving||(c.default.setRepeatSong(!g.default.repeat_song),y.default.syncRepeatSong())}function m(){return g.default.default_album_art}function _(e){g.default.default_album_art=e}function h(){return g.default.active_song.currentTime/g.default.active_song.duration*100}function P(e){"number"==typeof e&&e>0&&e<100&&(g.default.active_song.currentTime=g.default.active_song.duration*(e/100))}function b(e){g.default.debug=e}function S(){return g.default.active_metadata}function x(e){return g.default.songs[e]}function A(e,t){var a=g.default.playlists[e][t];return g.default.songs[a]}function L(e){return void 0==g.default.songs&&(g.default.songs=[]),g.default.songs.push(e),c.default.setNext(),g.default.songs.length-1}function M(e,t){void 0==g.default.songs&&(g.default.songs=[]),g.default.songs.push(e);var a=g.default.songs.length-1;return void 0!=g.default.playlists[t]?(g.default.playlists[t].push(a),c.default.setNextPlaylist(t),g.default.playlists[t].length-1):null}function k(e){return void 0!=g.default.songs[e]&&(g.default.songs.splice(e,1),!0)}function E(e,t){if(void 0==g.default.playlists[t])return!1;g.default.playlists[t].splice(e,1)}function T(e){s.default.playNow(e)}function C(e){s.default.playSongAtIndex(e)}function N(e,t){s.default.playPlaylistSongAtIndex(e,t)}function M(e,t){}function w(){s.default.play()}function B(){s.default.pause()}function I(){return g.default.active_song}function O(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;""==e||null==e?null==g.default.active_playlist||""==g.default.active_playlist?c.default.setNext():c.default.setNextPlaylist(g.default.active_playlist):c.default.setNextPlaylist(e)}function D(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;""==e||null==e?null==g.default.active_playlist||""==g.default.active_playlist?c.default.setPrev():c.default.setPrevPlaylist(g.default.active_playlist):c.default.setPrevPlaylist(e)}function H(){return g.default.songs}function q(e){for(var t=[],a=0;a2&&void 0!==arguments[2]?arguments[2]:null;null!=a&&o.default.checkNewPlaylist(a)&&o.default.setActivePlaylist(a),e=parseInt(e),o.default.changeSong(t),s.default.play(),y.default.syncMainPlayPause("playing"),null!=a&&y.default.syncPlaylistPlayPause(a,"playing"),y.default.syncSongPlayPause(a,t,"playing"),s.default.skipToLocation(e)}return{init:e,bindNewElements:t,getActivePlaylist:a,getPlaybackSpeed:l,getRepeat:u,getShuffle:n,getShufflePlaylist:d,setShuffle:f,setShufflePlaylist:r,setRepeat:p,setRepeatSong:v,getDefaultAlbumArt:m,setDefaultAlbumArt:_,getSongPlayedPercentage:h,setSongPlayedPercentage:P,setDebug:b,getActiveSongMetadata:S,getSongByIndex:x,getSongAtPlaylistIndex:A,addSong:L,addSongToPlaylist:M,removeSong:k,removeSongFromPlaylist:E,playNow:T,playSongAtIndex:C,playPlaylistSongAtIndex:N,play:w,pause:B,audio:I,next:O,prev:D,getSongs:H,getSongsInPlaylist:q,getSongsState:j,getSongsStatePlaylist:R,getActiveIndex:V,getActiveIndexState:U,getVersion:z,getBuffered:F,skipTo:W}}();t.default=m,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(1),s=l(n),d=a(6),o=l(d),f=function(){function e(e){u=e;var a=document.getElementsByTagName("head")[0],l=document.createElement("script");l.type="text/javascript",l.src="https://connect.soundcloud.com/sdk.js",l.onreadystatechange=t,l.onload=t,a.appendChild(l)}function t(){SC.initialize({client_id:i.default.soundcloud_client}),a()}function a(){for(var e=/^https?:\/\/(soundcloud.com|snd.sc)\/(.*)$/,t=0;t0)for(var a=document.querySelectorAll(t.join()),l=0;l0&&(l=e.hours+":"+l);for(var i=0,n=a.length;i0)for(var a=document.querySelectorAll(t.join()),l=0;l0&&(l=e.hours+":"+l));for(var i=0;i0&&(a=s+":"+a)}}for(var f=['.amplitude-time-remaining[amplitude-main-time-remaining="true"]','.amplitude-time-remaining[amplitude-playlist-main-time-remaining="'+u.default.active_playlist+'"]','.amplitude-time-remaining[amplitude-song-index="'+u.default.active_index+'"]'],r=document.querySelectorAll(f.join()),c=0;c0;a--){p(e,a,Math.floor(Math.random()*i.default.songs.length+1)-1)}i.default.shuffle_list=e}function c(e){for(var t=new Array(i.default.playlists[e].length),a=0;a0;l--){p(t,l,Math.floor(Math.random()*i.default.playlists[e].length+1)-1)}i.default.shuffled_playlists[e]=t}function p(e,t,a){var l=e[t];e[t]=e[a],e[a]=l}function y(e){i.default.active_playlist!=e&&a("playlist_changed"),i.default.active_playlist=e}function v(e){return/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.test(e)}function g(e){return!isNaN(e)&&parseInt(Number(e))==e&&!isNaN(parseInt(e,10))}return{resetConfig:e,writeDebugMessage:t,runCallback:a,changeSong:l,checkNewSong:u,checkNewAlbum:n,checkNewPlaylist:d,shuffleSongs:r,shufflePlaylistSongs:c,setActivePlaylist:y,isURL:v,isInt:g}}();t.default=f,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(10),s=l(n),d=function(){function e(e,t){s.default.syncCurrentHours(e.hours),s.default.syncCurrentMinutes(e.minutes),s.default.syncCurrentSeconds(e.seconds),s.default.syncCurrentTime(e),x(t),A(i.default.active_playlist,t),L(i.default.active_playlist,i.default.active_index,t),s.default.syncSongPlayedProgressBar(t)}function t(){s.default.resetCurrentHours(),s.default.resetCurrentMinutes(),s.default.resetCurrentSeconds(),s.default.resetCurrentTime()}function a(){for(var e=document.getElementsByClassName("amplitude-song-slider"),t=0;t=0?t[a].setAttribute("src",i.default.active_metadata[l]):t[a].innerHTML=i.default.active_metadata[l]:e.indexOf(l)>=0?""!=i.default.default_album_art?t[a].setAttribute("src",i.default.default_album_art):t[a].setAttribute("src",""):t[a].innerHTML="")}}function o(e,t){for(var a=["cover_art_url","station_art_url","podcast_episode_cover_art_url"],l=document.querySelectorAll('[amplitude-song-info][amplitude-playlist="'+t+'"]'),u=0;u=0?l[u].setAttribute("src",e[i]):l[u].innerHTML=e[i]:a.indexOf(i)>=0?""!=e.default_album_art?l[u].setAttribute("src",e.default_album_art):l[u].setAttribute("src",""):l[u].innerHTML="")}}function f(){for(var e=document.getElementsByClassName("amplitude-playback-speed"),t=0;t=0?t[a].setAttribute("src",i.default.songs[u][l]):t[a].innerHTML=i.default.songs[u][l])}}return{syncCurrentTime:e,resetTimes:t,resetSongSliders:a,resetSongPlayedProgressBars:u,resetSongBufferedProgressBars:l,setActiveContainer:n,displaySongMetadata:d,syncPlaybackSpeed:f,syncBufferedProgressBars:r,syncVolumeSliders:c,setPlayPauseButtonsToPause:p,setFirstSongInPlaylist:o,syncMainPlayPause:y,syncPlaylistPlayPause:v,syncSongPlayPause:g,syncRepeat:m,syncRepeatSong:h,syncRepeatPlaylist:_,syncMute:P,syncShuffle:b,syncPlaylistShuffle:S,syncMainSliderLocation:x,syncPlaylistSliderLocation:A,syncSongSliderLocation:L,syncVolumeSliderLocation:M,syncSongDuration:k,syncSongsMetaData:E}}();t.default=d,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(1),s=l(n),d=a(2),o=l(d),f=function(){function e(){s.default.runCallback("before_play"),i.default.active_metadata.live&&f(),/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)&&!i.default.paused&&f(),i.default.active_song.play(),i.default.active_song.playbackRate=i.default.playback_speed,s.default.runCallback("after_play")}function t(){s.default.runCallback("before_pause"),i.default.active_song.pause(),i.default.paused=!0,i.default.active_metadata.live&&d(),s.default.runCallback("after_pause")}function a(){s.default.runCallback("before_stop"),0!=i.default.active_song.currentTime&&(i.default.active_song.currentTime=0),i.default.active_song.pause(),i.default.active_metadata.live&&d(),s.default.runCallback("after_stop")}function l(e){0==e?o.default.syncMute(!0):o.default.syncMute(!1),i.default.active_song.volume=e/100}function u(e){i.default.active_metadata.live||(i.default.active_song.currentTime=i.default.active_song.duration*(song_percentage/100))}function n(e){i.default.active_song.addEventListener("canplaythrough",function(){i.default.active_song.duration>=e&&e>0?i.default.active_song.currentTime=e:s.default.writeDebugMessage("Amplitude can't skip to a location greater than the duration of the audio or less than 0")},{once:!0})}function d(){i.default.active_song.src="",i.default.active_song.load()}function f(){i.default.active_song.src=i.default.active_metadata.url,i.default.active_song.load()}function r(t){t.url?(i.default.active_song.src=t.url,i.default.active_metadata=t,i.default.active_album=t.album):s.default.writeDebugMessage("The song needs to have a URL!"),o.default.syncMainPlayPause("playing"),o.default.displaySongMetadata(),o.default.resetSongSliders(),o.default.resetSongPlayedProgressBars(),o.default.resetTimes(),e()}function c(t){a(),s.default.checkNewPlaylist(null)&&(s.default.setActivePlaylist(null),s.default.changeSong(t)),s.default.checkNewSong(t)&&s.default.changeSong(t),o.default.syncMainPlayPause("playing"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),e()}function p(t,l){a();var u=i.default.playlists[l][t];s.default.checkNewPlaylist(l)&&(s.default.setActivePlaylist(l),s.default.changeSong(u)),s.default.checkNewSong(u)&&s.default.changeSong(u),o.default.syncMainPlayPause("playing"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),e()}function y(e){i.default.playback_speed=e,i.default.active_song.playbackRate=i.default.playback_speed}return{play:e,pause:t,stop:a,setVolume:l,setSongLocation:u,skipToLocation:n,disconnectStream:d,reconnectStream:f,playNow:r,playSongAtIndex:c,playPlaylistSongAtIndex:p,setPlaybackSpeed:y}}();t.default=f,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(1),s=l(n),d=a(7),o=l(d),f=function(){function e(){s.default.writeDebugMessage("Beginning initialization of event handlers.."),document.addEventListener("touchmove",function(){i.default.is_touch_moving=!0}),document.addEventListener("touchend",function(){i.default.is_touch_moving&&(i.default.is_touch_moving=!1)}),t(),a(),l(),u(),n(),d(),f(),r(),c(),p(),y(),v(),g(),m(),_(),h(),P(),b(),S()}function t(){i.default.active_song.removeEventListener("timeupdate",o.default.updateTime),i.default.active_song.addEventListener("timeupdate",o.default.updateTime),i.default.active_song.removeEventListener("durationchange",o.default.updateTime),i.default.active_song.addEventListener("durationchange",o.default.updateTime)}function a(){document.removeEventListener("keydown",s.default.keydown),document.addEventListener("keydown",o.default.keydown)}function l(){i.default.active_song.removeEventListener("ended",o.default.songEnded),i.default.active_song.addEventListener("ended",o.default.songEnded)}function u(){i.default.active_song.removeEventListener("progress",o.default.progess),i.default.active_song.addEventListener("progress",o.default.progress)}function n(){for(var e=document.getElementsByClassName("amplitude-play"),t=0;t0||navigator.userAgent.match(/Trident.*rv\:11\./)?(a[l].removeEventListener("change",o.default.songSlider),a[l].addEventListener("change",o.default.songSlider)):(a[l].removeEventListener("input",o.default.songSlider),a[l].addEventListener("input",o.default.songSlider))}function g(){for(var e=window.navigator.userAgent,t=e.indexOf("MSIE "),a=document.getElementsByClassName("amplitude-volume-slider"),l=0;l0||navigator.userAgent.match(/Trident.*rv\:11\./)?(a[l].removeEventListener("change",o.default.volumeSlider),a[l].addEventListener("change",o.default.volumeSlider)):(a[l].removeEventListener("input",o.default.volumeSlider),a[l].addEventListener("input",o.default.volumeSlider))}function m(){for(var e=document.getElementsByClassName("amplitude-next"),t=0;t=60&&(l=Math.floor(a/60),(a%=60)<10&&(a="0"+a)),e.seconds=t,e.minutes=a,e.hours=l,e}function t(){var e={},t=(Math.floor(i.default.active_song.duration%60)<10?"0":"")+Math.floor(i.default.active_song.duration%60),a=Math.floor(i.default.active_song.duration/60),l="0";return a<10&&(a="0"+a),a>=60&&(l=Math.floor(a/60),(a%=60)<10&&(a="0"+a)),e.seconds=t,e.minutes=a,e.hours=l,e}function a(){return i.default.active_song.currentTime/i.default.active_song.duration*100}function l(e){o.default.setPlaybackSpeed(e)}function u(e,t){null==t?(i.default.repeat=e,s.default.syncRepeat()):(i.default.repeat_statuses[t]=e,s.default.syncRepeatPlaylist(t))}function n(e){i.default.repeat_song=e}function d(){i.default.active_song.paused?(s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),o.default.play()):(s.default.syncMainPlayPause("paused"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),o.default.pause())}function f(e){r.default.checkNewPlaylist(e)&&(r.default.setActivePlaylist(e),i.default.shuffled_statuses[e]?r.default.changeSong(i.default.shuffled_playlists[e][0].original_index):r.default.changeSong(i.default.playlists[e][0])),i.default.active_song.paused?(s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),o.default.play()):(s.default.syncMainPlayPause("paused"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),o.default.pause())}function p(e,t){r.default.checkNewPlaylist(e)&&(r.default.setActivePlaylist(e),r.default.changeSong(t)),r.default.checkNewSong(t)&&r.default.changeSong(t),i.default.active_song.paused?(s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"playing"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"playing"),o.default.play()):(s.default.syncMainPlayPause("paused"),s.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),s.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),o.default.pause())}function y(e){null==e?(i.default.shuffle_on?(i.default.shuffle_on=!1,i.default.shuffle_list={}):(i.default.shuffle_on=!0,r.default.shuffleSongs()),s.default.syncShuffle(i.default.shuffle_on)):(i.default.shuffled_statuses[e]?(i.default.shuffled_statuses[e]=!1,i.default.shuffled_playlists[e]=[]):(i.default.shuffled_statuses[e]=!0,r.default.shufflePlaylistSongs(e)),s.default.syncPlaylistShuffle(i.default.shuffled_statuses[e],e))}function v(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=0,a=!1;i.default.repeat_song?t=i.default.shuffle_on?i.default.shuffle_active_index:i.default.active_index:i.default.shuffle_on?parseInt(i.default.shuffle_active_index)+11&&void 0!==arguments[1]&&arguments[1],a=0,l=!1;if(i.default.repeat_song)a=i.default.shuffled_statuses[e]?i.default.shuffled_playlists[e][i.default.shuffled_active_indexes[e]].original_index:i.default.active_index;else if(i.default.shuffled_statuses[e]){var u=parseInt(i.default.shuffled_active_indexes[e]);u+1=0?(i.default.shuffle_active_index=parseInt(i.default.shuffle_active_index)-1,e=i.default.shuffle_list[parseInt(i.default.shuffle_active_index)].original_index):(i.default.shuffle_active_index=i.default.shuffle_list.length-1,e=i.default.shuffle_list[parseInt(i.default.shuffle_list.length)-1].original_index):(parseInt(i.default.active_index)-1>=0?i.default.active_index=parseInt(i.default.active_index)-1:i.default.active_index=i.default.songs.length-1,e=i.default.active_index),o.default.stop(),r.default.changeSong(e),o.default.play(),s.default.syncMainPlayPause("playing"),s.default.syncSongPlayPause(null,e,"playing"),r.default.runCallback("after_prev")}function _(e){var t=0;if(i.default.shuffled_statuses[e]){var a=parseInt(i.default.shuffled_active_indexes[e]);a-1>=0?(i.default.shuffled_active_indexes[e]=a-1,t=i.default.shuffled_playlists[e][i.default.shuffled_active_indexes[e]].original_index):(i.default.shuffled_active_indexes[e]=i.default.shuffled_playlists[e].length-1,t=i.default.shuffled_playlists[e][i.default.shuffled_playlists[e].length-1].original_index)}else{var l=i.default.playlists[e].indexOf(parseInt(i.default.active_index));i.default.active_index=l-1>=0?parseInt(i.default.playlists[e][l-1]):parseInt(i.default.playlists[e][i.default.playlists[e].length-1]),t=i.default.active_index}o.default.stop(),r.default.changeSong(t),r.default.setActivePlaylist(e),o.default.play(),s.default.syncMainPlayPause("playing"),s.default.syncPlaylistPlayPause(e,"playing"),s.default.syncSongPlayPause(e,t,"playing"),r.default.runCallback("after_prev")}function h(e){if(void 0!=i.default.bindings[e])switch(i.default.bindings[e]){case"play_pause":p(i.default.active_playlist,i.default.active_index);break;case"next":""==i.default.active_playlist||null==i.default.active_playlist?v():g(i.default.active_playlist);break;case"prev":""==i.default.active_playlist||null==i.default.active_playlist?c.setPrev():c.setPrevPlaylist(i.default.active_playlist);break;case"stop":s.default.setPlayPauseButtonsToPause(),o.default.stop();break;case"shuffle":""==i.default.active_playlist||null==i.default.active_playlist?AmplitudesEventHelpers.setShuffle(null):AmplitudeEvenstHelpers.setShuffle(i.default.active_playlist);break;case"repeat":c.setRepeat(!i.default.repeat),s.default.syncRepeat()}}return{computeCurrentTimes:e,computeSongDuration:t,computeSongCompletionPercentage:a,setPlaybackSpeed:l,setRepeat:u,setRepeatSong:n,setMainPlayPause:d,setPlaylistPlayPause:f,setSongPlayPause:p,setShuffle:y,setNext:v,setNextPlaylist:g,setPrev:m,setPrevPlaylist:_,runKeyEvent:h}}();t.default=c,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=a(0),n=l(i),s=a(3),d=l(s),o=a(1),f=l(o),r=a(4),c=l(r),p=a(9),y=l(p),v=a(2),g=l(v),m=function(){function e(e){var t=!1;if(f.default.resetConfig(),c.default.initializeEvents(),n.default.debug=void 0!=e.debug&&e.debug,e.songs?0!=e.songs.length?(n.default.songs=e.songs,t=!0):f.default.writeDebugMessage("Please add some songs, to your songs object!"):f.default.writeDebugMessage("Please provide a songs object for AmplitudeJS to run!"),e.playlists&&l(e.playlists)>0&&(n.default.playlists=e.playlists,m(),i(),s(),o(),r(),p(),v()),t){n.default.soundcloud_client=void 0!=e.soundcloud_client?e.soundcloud_client:"",n.default.soundcloud_use_art=void 0!=e.soundcloud_use_art?e.soundcloud_use_art:"";var u={};""!=n.default.soundcloud_client?(u=e,y.default.loadSoundCloud(u)):a(e)}f.default.writeDebugMessage("Initialized With: "),f.default.writeDebugMessage(n.default)}function t(){c.default.initializeEvents(),g.default.displaySongMetadata()}function a(e){void 0!=e.start_song?f.default.isInt(e.start_song)?f.default.changeSong(e.start_song):f.default.writeDebugMessage("You must enter an integer index for the start song."):f.default.changeSong(0),void 0!=e.shuffle_on&&e.shuffle_on&&(n.default.shuffle_on=!0,f.default.shuffleSongs(),g.default.syncShuffle(n.default.shuffle_on),f.default.changeSong(n.default.shuffle_list[0].original_index)),n.default.continue_next=void 0==e.continue_next||e.continue_next,n.default.playback_speed=void 0!=e.playback_speed?e.playback_speed:1,d.default.setPlaybackSpeed(n.default.playback_speed),n.default.active_song.preload=void 0!=e.preload?e.preload:"auto",n.default.callbacks=void 0!=e.callbacks?e.callbacks:{},n.default.bindings=void 0!=e.bindings?e.bindings:{},n.default.volume=void 0!=e.volume?e.volume:50,n.default.volume_increment=void 0!=e.volume_increment?e.volume_increment:5,n.default.volume_decrement=void 0!=e.volume_decrement?e.volume_decrement:5,d.default.setVolume(n.default.volume),g.default.syncVolumeSliders(),void 0!=e.default_album_art?n.default.default_album_art=e.default_album_art:n.default.default_album_art="",g.default.resetTimes(),g.default.setPlayPauseButtonsToPause(),g.default.syncSongsMetaData(),e.autoplay&&(""==e.starting_playlist?n.default.active_playlist=null:n.default.active_playlist=e.starting_playlist,g.default.syncMainPlayPause("playing"),g.default.syncSongPlayPause(n.default.active_playlist,0,"playing"),d.default.play()),void 0!=e.starting_playlist&&""!=e.starting_playlist&&(n.default.active_playlist=e.starting_playlist,void 0!=e.starting_playlist_song&&""!=e.starting_playlist_song?void 0!=u(e.playlists[e.starting_playlist][parseInt(e.starting_playlist_song)])?f.default.changeSong(e.playlists[e.starting_playlist][parseInt(e.starting_playlist_song)]):(f.default.changeSong(e.playlists[e.starting_playlist][0]),f.default.writeDebugMessage("The index of "+e.starting_playlist_song+" does not exist in the playlist "+e.starting_playlist)):f.default.changeSong(e.playlists[e.starting_playlist][0]),g.default.syncMainPlayPause("paused"),g.default.syncSongPlayPause(n.default.active_playlist,0,"paused")),f.default.runCallback("after_init")}function l(e){var t=0,a=void 0;for(a in e)e.hasOwnProperty(a)&&t++;return f.default.writeDebugMessage("You have "+t+" playlist(s) in your config"),t}function i(){for(var e in n.default.playlists)if(n.default.playlists.hasOwnProperty(e)&&n.default.playlists[e].songs)for(var t=0;t=0){var e=i.default.active_song.buffered.end(i.default.active_song.buffered.length-1),t=i.default.active_song.duration;i.default.buffered=e/t*100}if(o.default.syncBufferedProgressBars(),!i.default.active_metadata.live){var a=s.default.computeCurrentTimes(),l=s.default.computeSongCompletionPercentage(),u=s.default.computeSongDuration();o.default.syncCurrentTime(a,l),o.default.syncSongDuration(a,u),p.default.runCallback("time_update")}},keydown:function(e){s.default.runKeyEvent(e.which)},songEnded:function(){i.default.continue_next?""==i.default.active_playlist||null==i.default.active_playlist?s.default.setNext(!0):s.default.setNextPlaylist(i.default.active_playlist,!0):i.default.is_touch_moving||(o.default.setPlayPauseButtonsToPause(),r.default.stop())},progress:function(){if(i.default.active_song.buffered.length-1>=0){var e=i.default.active_song.buffered.end(i.default.active_song.buffered.length-1),t=i.default.active_song.duration;i.default.buffered=e/t*100}o.default.syncBufferedProgressBars()},play:function(){if(!i.default.is_touch_moving){var e=this.getAttribute("amplitude-song-index"),t=this.getAttribute("amplitude-playlist");null==t&&null==e&&s.default.setSongPlayPause(i.default.active_playlist,i.default.active_index),null!=t&&""!=t&&(p.default.checkNewPlaylist(t)?(p.default.setActivePlaylist(t),null!=e?(p.default.changeSong(e),s.default.setPlaylistPlayPause(t)):(p.default.changeSong(i.default.playlists[t][0]),s.default.setPlaylistPlayPause(t))):null!=e?(p.default.changeSong(e),s.default.setPlaylistPlayPause(t)):(p.default.changeSong(i.default.active_index),s.default.setPlaylistPlayPause(t))),null!=t&&""!=t||null==e||""==e||((p.default.checkNewSong(e)||i.default.active_playlist!=t)&&p.default.changeSong(e),s.default.setSongPlayPause(t,e))}},pause:function(){if(!i.default.is_touch_moving){var e=this.getAttribute("amplitude-song-index"),t=this.getAttribute("amplitude-playlist");null==e&&null==t&&(s.default.setSongPlayPause(i.default.active_playlist,i.default.active_index),r.default.pause()),(null!=t||""!=t&&i.default.active_playlist==t)&&(o.default.syncMainPlayPause("paused"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),r.default.pause()),null!=t&&""!=t||e!=i.default.active_index||(o.default.syncMainPlayPause("paused"),o.default.syncPlaylistPlayPause(i.default.active_playlist,"paused"),o.default.syncSongPlayPause(i.default.active_playlist,i.default.active_index,"paused"),r.default.pause())}},playPause:function(){if(!i.default.is_touch_moving)if(null!=this.getAttribute("amplitude-main-play-pause"))s.default.setMainPlayPause();else if(null!=this.getAttribute("amplitude-playlist-main-play-pause")){var e=this.getAttribute("amplitude-playlist");s.default.setPlaylistPlayPause(e)}else{var t=this.getAttribute("amplitude-playlist"),a=this.getAttribute("amplitude-song-index");s.default.setSongPlayPause(t,a)}},stop:function(){i.default.is_touch_moving||(o.default.setPlayPauseButtonsToPause(),r.default.stop())},mute:function(){i.default.is_touch_moving||(0==i.default.volume?(i.default.active_song.muted=!1,i.default.volume=i.default.pre_mute_volume,o.default.syncMute(!1)):(i.default.active_song.muted=!0,i.default.pre_mute_volume=i.default.volume,i.default.volume=0,o.default.syncMute(!0)),r.default.setVolume(i.default.volume),o.default.syncVolumeSliders(i.default.volume))},volumeUp:function(){i.default.is_touch_moving||(i.default.volume+i.default.volume_increment<=100?i.default.volume=i.default.volume+i.default.volume_increment:i.default.volume=100,r.default.setVolume(i.default.volume),o.default.syncVolumeSliders(i.default.volume))},volumeDown:function(){i.default.is_touch_moving||(i.default.volume-i.default.volume_increment>0?i.default.volume=i.default.volume-i.default.volume_increment:i.default.volume=0,r.default.setVolume(i.default.volume),o.default.syncVolumeSliders(i.default.volume))},songSlider:function(){var e=this.value;if(null!=this.getAttribute("amplitude-main-song-slider")){if(!i.default.active_metadata.live){var t=i.default.active_song.duration*(e/100);isFinite(t)&&(i.default.active_song.currentTime=t)}o.default.syncMainSliderLocation(e),""!=i.default.active_playlist&&null!=i.default.active_playlist&&o.default.syncPlaylistSliderLocation(i.default.active_playlist,e)}if(null!=this.getAttribute("amplitude-playlist-song-slider")){var a=this.getAttribute("amplitude-playlist");i.default.active_playlist==a&&(i.default.active_metadata.live||(i.default.active_song.currentTime=i.default.active_song.duration*(e/100)),o.default.syncMainSliderLocation(e),o.default.syncPlaylistSliderLocation(a,e))}if(null==this.getAttribute("amplitude-playlist-song-slider")&&null==this.getAttribute("amplitude-main-song-slider")){var l=this.getAttribute("amplitude-playlist"),u=this.getAttribute("amplitude-song-index");i.default.active_index==u&&(i.default.active_metadata.live||(i.default.active_song.currentTime=i.default.active_song.duration*(e/100)),o.default.syncMainSliderLocation(),""!=i.default.active_playlist&&null!=i.default.active_playlist&&i.default.active_playlist==l&&o.default.syncPlaylistSliderLocation(l,location),o.default.syncSongSliderLocation(l,u,location))}},volumeSlider:function(){r.default.setVolume(this.value),o.default.syncVolumeSliderLocation(this.value)},next:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))""==i.default.active_playlist||null==i.default.active_playlist?s.default.setNext():s.default.setNextPlaylist(i.default.active_playlist);else{var e=this.getAttribute("amplitude-playlist");s.default.setNextPlaylist(e)}},prev:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))""==i.default.active_playlist||null==i.default.active_playlist?s.default.setPrev():s.default.setPrevPlaylist(i.default.active_playlist);else{var e=this.getAttribute("amplitude-playlist");s.default.setPrevPlaylist(e)}},shuffle:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))s.default.setShuffle(null);else{var e=this.getAttribute("amplitude-playlist");s.default.setShuffle(e)}},repeat:function(){if(!i.default.is_touch_moving)if(""==this.getAttribute("amplitude-playlist")||null==this.getAttribute("amplitude-playlist"))s.default.setRepeat(!i.default.repeat,null);else{var e=this.getAttribute("amplitude-playlist");s.default.setRepeat(!i.default.repeat_statuses[e],e)}},repeatSong:function(){i.default.is_touch_moving||(s.default.setRepeatSong(!i.default.repeat_song),o.default.syncRepeatSong())},playbackSpeed:function(){if(!i.default.is_touch_moving){switch(i.default.playback_speed){case 1:s.default.setPlaybackSpeed(1.5);break;case 1.5:s.default.setPlaybackSpeed(2);break;case 2:s.default.setPlaybackSpeed(1)}o.default.syncPlaybackSpeed()}},skipTo:function(){if(!i.default.is_touch_moving)if(this.hasAttribute("amplitude-playlist")){var e=this.getAttribute("amplitude-playlist");p.default.checkNewPlaylist(e)&&p.default.setActivePlaylist(e);var t=parseInt(this.getAttribute("amplitude-location")),a=parseInt(this.getAttribute("amplitude-song-index"));p.default.changeSong(a),r.default.play(),o.default.syncMainPlayPause("playing"),o.default.syncPlaylistPlayPause(e,"playing"),o.default.syncSongPlayPause(e,a,"playing"),r.default.skipToLocation(t)}else{var l=parseInt(this.getAttribute("amplitude-location")),u=parseInt(this.getAttribute("amplitude-song-index"));p.default.changeSong(u),r.default.play(),o.default.syncMainPlayPause("playing"),o.default.syncSongPlayPause(null,u,"playing"),r.default.skipToLocation(l)}}},e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(6),i=l(u),n=a(3),s=l(n),d=a(1),o=l(d),f=a(4),r=(l(f),a(5)),c=l(r),p=a(2),y=l(p),v=a(0),g=l(v),m=function(){function e(e){i.default.initialize(e)}function t(){i.default.rebindDisplay()}function a(){return g.default.active_playlist}function l(){return g.default.playback_speed}function u(){return g.default.repeat}function n(){return g.default.shuffle_on}function d(e){return g.default.shuffled_statuses[e]}function f(){c.default.setShuffle(null)}function r(e){c.default.setShuffle(e)}function p(){g.default.is_touch_moving||(c.default.setRepeat(!g.default.repeat),y.default.syncRepeat())}function v(){g.default.is_touch_moving||(c.default.setRepeatSong(!g.default.repeat_song),y.default.syncRepeatSong())}function m(){return g.default.default_album_art}function _(e){g.default.default_album_art=e}function h(){return g.default.active_song.currentTime/g.default.active_song.duration*100}function P(e){"number"==typeof e&&e>0&&e<100&&(g.default.active_song.currentTime=g.default.active_song.duration*(e/100))}function b(e){g.default.debug=e}function S(){return g.default.active_metadata}function x(e){return g.default.songs[e]}function A(e,t){var a=g.default.playlists[e][t];return g.default.songs[a]}function L(e){return void 0==g.default.songs&&(g.default.songs=[]),g.default.songs.push(e),c.default.setNext(),g.default.songs.length-1}function M(e,t){void 0==g.default.songs&&(g.default.songs=[]),g.default.songs.push(e);var a=g.default.songs.length-1;return void 0!=g.default.playlists[t]?(g.default.playlists[t].push(a),c.default.setNextPlaylist(t),g.default.playlists[t].length-1):null}function k(e){return void 0!=g.default.songs[e]&&(g.default.songs.splice(e,1),!0)}function E(e,t){if(void 0==g.default.playlists[t])return!1;g.default.playlists[t].splice(e,1)}function T(e){s.default.playNow(e)}function C(e){s.default.playSongAtIndex(e)}function N(e,t){s.default.playPlaylistSongAtIndex(e,t)}function M(e,t){}function w(){s.default.play()}function B(){s.default.pause()}function I(){return g.default.active_song}function O(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;""==e||null==e?null==g.default.active_playlist||""==g.default.active_playlist?c.default.setNext():c.default.setNextPlaylist(g.default.active_playlist):c.default.setNextPlaylist(e)}function D(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;""==e||null==e?null==g.default.active_playlist||""==g.default.active_playlist?c.default.setPrev():c.default.setPrevPlaylist(g.default.active_playlist):c.default.setPrevPlaylist(e)}function H(){return g.default.songs}function q(e){for(var t=[],a=0;a2&&void 0!==arguments[2]?arguments[2]:null;null!=a&&o.default.checkNewPlaylist(a)&&o.default.setActivePlaylist(a),e=parseInt(e),o.default.changeSong(t),s.default.play(),y.default.syncMainPlayPause("playing"),null!=a&&y.default.syncPlaylistPlayPause(a,"playing"),y.default.syncSongPlayPause(a,t,"playing"),s.default.skipToLocation(e)}return{init:e,bindNewElements:t,getActivePlaylist:a,getPlaybackSpeed:l,getRepeat:u,getShuffle:n,getShufflePlaylist:d,setShuffle:f,setShufflePlaylist:r,setRepeat:p,setRepeatSong:v,getDefaultAlbumArt:m,setDefaultAlbumArt:_,getSongPlayedPercentage:h,setSongPlayedPercentage:P,setDebug:b,getActiveSongMetadata:S,getSongByIndex:x,getSongAtPlaylistIndex:A,addSong:L,addSongToPlaylist:M,removeSong:k,removeSongFromPlaylist:E,playNow:T,playSongAtIndex:C,playPlaylistSongAtIndex:N,play:w,pause:B,audio:I,next:O,prev:D,getSongs:H,getSongsInPlaylist:q,getSongsState:j,getSongsStatePlaylist:R,getActiveIndex:V,getActiveIndexState:U,getVersion:z,getBuffered:F,skipTo:W}}();t.default=m,e.exports=t.default},function(e,t,a){"use strict";function l(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var u=a(0),i=l(u),n=a(1),s=l(n),d=a(6),o=l(d),f=function(){function e(e){u=e;var a=document.getElementsByTagName("head")[0],l=document.createElement("script");l.type="text/javascript",l.src="https://connect.soundcloud.com/sdk.js",l.onreadystatechange=t,l.onload=t,a.appendChild(l)}function t(){SC.initialize({client_id:i.default.soundcloud_client}),a()}function a(){for(var e=/^https?:\/\/(soundcloud.com|snd.sc)\/(.*)$/,t=0;t0)for(var a=document.querySelectorAll(t.join()),l=0;l0&&(l=e.hours+":"+l);for(var i=0,n=a.length;i0)for(var a=document.querySelectorAll(t.join()),l=0;l0&&(l=e.hours+":"+l));for(var i=0;i0&&(a=s+":"+a)}}for(var f=['.amplitude-time-remaining[amplitude-main-time-remaining="true"]','.amplitude-time-remaining[amplitude-playlist-main-time-remaining="'+u.default.active_playlist+'"]','.amplitude-time-remaining[amplitude-song-index="'+u.default.active_index+'"]'],r=document.querySelectorAll(f.join()),c=0;c