]> littlesong.place Git - littlesongplace.git/commitdiff
Add shuffle checkbox to song list
authorChris Fulljames <christianfulljames@gmail.com>
Wed, 26 Feb 2025 01:09:12 +0000 (20:09 -0500)
committerChris Fulljames <christianfulljames@gmail.com>
Wed, 26 Feb 2025 01:09:12 +0000 (20:09 -0500)
static/player.js
static/styles.css
templates/song-list.html

index cdee152e37b6f898c91f5149ea6c3da0c8acf4a6..a2dfb7e9d0465ebb902b1a7aa69e612150e2b42d 100644 (file)
@@ -155,8 +155,15 @@ function songUpdate() {
 }
 
 // Add event listeners
+var m_firstLoad = true;
 document.addEventListener("DOMContentLoaded", (event) => {
 
+    // The player never gets rebuilt, so we only need to set it up the first time
+    if (!m_firstLoad) {
+        return;
+    }
+    m_firstLoad = false;
+
     // Audio playback position while playing
     var audio = document.getElementById("player-audio");
     audio.addEventListener("timeupdate", songUpdate);
index fa18e73dddbdb3d1f264412e9f0eea7aae04b403..b3006ae538df8bc1297f79af03e5b2fec5250cd5 100644 (file)
@@ -298,13 +298,17 @@ input[type=file] {
 }
 
 /* Song Entry in Song List */
-div.song-list {
+.song-list-controls {
+    padding-bottom: 5px;
+}
+
+div.song-list-songs {
     display: flex;
     flex-direction: column;
     gap: 10px;
 }
 
-.song-list .song {
+.song-list-songs .song {
     box-shadow: 0px 0px 5px 0px;
     border-radius: 10px;
 }
index 775125c60102b189f233c2f40a7702f7c0723335..d135fc72a294b2f47eeb8e4237adbbf58f31e216 100644 (file)
@@ -1,33 +1,39 @@
 {% from "song-macros.html" import song_info, song_details %}
 
 <div class="song-list">
-{% for song in songs %}
-    <div class="song" data-song="{{ song.json() }}">
-        <div class="song-main">
-            <div class="song-list-pfp-container">
-                {%- if song.user_has_pfp %}
-                <!-- Profile Picture -->
-                <img class="small-pfp" src="/pfp/{{ song.userid }}" onerror="this.style.display = 'none'" width="32" height="32" />
-                {%- endif %}
-            </div>
+    <div class="song-list-controls">
+        <label><input type="checkbox" name="shuffle" onchange="shuffleSongList(event)">Shuffle</label>
+    </div>
+
+    <div class="song-list-songs">
+        {% for song in songs %}
+        <div class="song" data-song="{{ song.json() }}">
+            <div class="song-main">
+                <div class="song-list-pfp-container">
+                    {%- if song.user_has_pfp %}
+                    <!-- Profile Picture -->
+                    <img class="small-pfp" src="/pfp/{{ song.userid }}" onerror="this.style.display = 'none'" width="32" height="32" />
+                    {%- endif %}
+                </div>
 
-            {{ song_info(song) | indent(12) }}
+                {{ song_info(song) | indent(12) }}
 
-            <div class="song-buttons">
-                <!-- Details Button -->
-                <button onclick="return showDetails(event)" class="song-list-button details-toggle" title="Toggle Details">
-                    <img class="lsp_btn_show02" alt="Show Details">
-                </button>
+                <div class="song-buttons">
+                    <!-- Details Button -->
+                    <button onclick="return showDetails(event)" class="song-list-button details-toggle" title="Toggle Details">
+                        <img class="lsp_btn_show02" alt="Show Details">
+                    </button>
 
-                <!-- Play Button -->
-                <button onclick="return play(event)" class="song-list-button" title="Play">
-                    <img class="lsp_btn_play02" alt="Play">
-                </button>
+                    <!-- Play Button -->
+                    <button onclick="return play(event)" class="song-list-button" title="Play">
+                        <img class="lsp_btn_play02" alt="Play">
+                    </button>
+                </div>
             </div>
+            {{ song_details(song, current_user_playlists) | indent(8) }}
         </div>
-        {{ song_details(song, current_user_playlists) | indent(8) }}
+        {% endfor %}
     </div>
-{% endfor %}
 </div>
 
 <script>
@@ -51,4 +57,33 @@ function showDetails(event) {
     }
     return false;
 }
+
+function shuffleSongList(event) {
+    var songList = event.target.closest(".song-list");
+    var songs = songList.querySelector(".song-list-songs");
+    if (event.target.checked) {
+        // Store original list so it can be restored later
+        songList.dataset.original = songs.innerHTML;
+
+        // Shuffle
+        var songElements = [];
+        while (songs.firstElementChild) {
+            songElements.push(songs.lastElementChild);
+            songs.removeChild(songs.lastElementChild);
+        }
+        for (let i = songElements.length - 1; i >= 0; i --) {
+            const j = Math.floor(Math.random() * (i + 1));
+            [songElements[i], songElements[j]] = [songElements[j], songElements[i]];
+        }
+        for (const child of songElements) {
+            songs.appendChild(child);
+        }
+    }
+    else {
+        // Unshuffle
+        if (songList.dataset.original) {
+            songs.innerHTML = songList.dataset.original;
+        }
+    }
+}
 </script>