]> littlesong.place Git - littlesongplace.git/commitdiff
Use HTML for AJAX requests instead of XML
authorChris Fulljames <christianfulljames@gmail.com>
Sat, 22 Feb 2025 17:22:02 +0000 (12:22 -0500)
committerChris Fulljames <christianfulljames@gmail.com>
Sat, 22 Feb 2025 17:22:02 +0000 (12:22 -0500)
15 files changed:
main.py
templates/activity.html
templates/base.html
templates/base.json [deleted file]
templates/comment.html
templates/edit-song.html
templates/index.html
templates/login.html
templates/news.html
templates/playlist.html
templates/profile.html
templates/signup.html
templates/song-list.html
templates/song.html
templates/songs-by-tag.html

diff --git a/main.py b/main.py
index 3aebd3d6c8852ac6af12efeb84118a730f57f121..0f685651d6f928902b61b8a38097fdd8bf8ca1e4 100644 (file)
--- a/main.py
+++ b/main.py
@@ -13,7 +13,6 @@ from datetime import datetime, timezone
 from logging.handlers import RotatingFileHandler
 from pathlib import Path, PosixPath
 from typing import Optional
-from xml.sax.saxutils import escape
 
 import bcrypt
 import bleach
@@ -931,12 +930,9 @@ def get_current_user_playlists():
 
 @app.context_processor
 def inject_global_vars():
-    use_xml = request.headers["Accept"] == "application/xml"
     return dict(
         gif_data=get_gif_data(),
         current_user_playlists=get_current_user_playlists(),
-        use_xml=use_xml,
-        escape=escape,
         bgcolor="#e8e6b5",
         fgcolor="#695c73",
         accolor="#9373a9",
index 3aa09380f47a6705556290519552de9d5033c47c..d802b5bd1f5a2033fc452a6abb6d7259a0ca4b09 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}Activity{% endblock %}
 
index 8e5b2824bbbee5c9b8baac658ca5b01b063deee2..2f7c97cedbbd60b33d869d6ba0064bb1d82d962b 100644 (file)
@@ -6,36 +6,49 @@
         <link rel="icon" type="image/x-icon" href="/static/lsp_notes.png"/>
         <script src="/static/player.js"></script>
         <meta name="viewport" content="width=device-width, initial-scale=1">
+
+        <!-- Include coloris library for color picker -->
+        <link rel="stylesheet" href="/static/coloris.min.css"/>
+        <script src="/static/coloris.min.js"></script>
+
         <!-- Page-specific head fields -->
         {% block head %}
         {% endblock %}
         <script>
-            document.addEventListener("click", (event) => {
-                // Handle all clicks on links
-                if (!event.target.matches("a")) {
-                    return;
-                }
+            document.addEventListener("DOMContentLoaded", (e) => {
+
+                // Handle link clicks with AJAX
+                document.querySelectorAll("a").forEach((anchor) => {
+                    anchor.removeEventListener("click", onLinkClick);
+                    anchor.addEventListener("click", onLinkClick);
+                });
+
+                // Handle form submissions with AJAX
+                document.querySelectorAll("form").forEach((form) => {
+                    form.removeEventListener("submit", onFormSubmit);
+                    form.addEventListener("submit", onFormSubmit);
+                });
+            });
 
-                var targetUrl = new URL(event.target.href);
+            function onLinkClick(event) {
+                var targetUrl = new URL(event.currentTarget.href);
                 if (urlIsOnSameSite(targetUrl)) {
                     event.preventDefault();
+                    event.stopPropagation();
                     fetch(targetUrl, {redirect: "follow"}).then(handleAjaxResponse);
                 }
-            });
+            }
 
-            document.addEventListener("DOMContentLoaded", (e) => {
-                document.querySelectorAll("form").forEach((form) => {
-                    form.addEventListener("submit", (event) => {
-                        var targetUrl = new URL(event.target.action);
-                        if (urlIsOnSameSite(targetUrl)) {
-                            event.preventDefault();
-                            var formData = new FormData(event.target);
-                            fetch(targetUrl, {redirect: "follow", body: formData, method: event.target.method})
-                                .then(handleAjaxResponse);
-                        }
-                    });
-                });
-            });
+            function onFormSubmit(event) {
+                var targetUrl = new URL(event.target.action);
+                if (urlIsOnSameSite(targetUrl)) {
+                    event.preventDefault();
+                    event.stopPropagation();
+                    var formData = new FormData(event.target);
+                    fetch(targetUrl, {redirect: "follow", body: formData, method: event.target.method})
+                        .then(handleAjaxResponse);
+                }
+            }
 
             function urlIsOnSameSite(targetUrl) {
                 var currentUrl = new URL(window.location.href);
@@ -49,7 +62,6 @@
 
                 // Get page content from XML response
                 var text = await response.text();
-                console.log(text);
                 window.history.pushState(text, "", url);
 
                 updatePageState(text);
                 }
                 var parser = new DOMParser();
                 data = parser.parseFromString(data, "text/html");
-                //console.log(data.querySelector("body").textContent);
-                var body = parser.parseFromString(data.querySelector("body").innerHTML, "text/html");
-                //console.log(body.documentElement.textContent);
-                document.getElementById("main").innerHTML = body.documentElement.textContent;
+                var newMainDiv = data.getElementById("main");
+                var oldMainDiv = document.getElementById("main");
+                document.body.replaceChild(newMainDiv, oldMainDiv);
                 document.title = data.title;
 
+                // Load inline scripts (DOMParser disables these by default)
+                var scripts = document.getElementById("main").getElementsByTagName("script");
+                for (const script of scripts) {
+                    var newScript = document.createElement("script");
+                    newScript.type = script.type;
+                    newScript.text = script.text;
+                    script.parentElement.replaceChild(newScript, script);
+                }
+
+                // Delete old color picker (will be recreated on DOMContentLoaded)
+                document.getElementById("clr-picker").remove();
+
                 // Trigger event to signal new page has loaded
                 var event = new Event("DOMContentLoaded");
                 document.dispatchEvent(event);
 
-                // Update page colors
-                var rootStyle = document.documentElement.style;
-                rootStyle.setProperty("--yellow", data.bgcolor);
-                rootStyle.setProperty("--black", data.fgcolor);
-                rootStyle.setProperty("--purple", data.accolor);
-
                 // Refresh navbar in case logged-in status changed
-                updateNavbar(data.username);
-                updateImageColors();
+                updateNavbar(newMainDiv.dataset.username);
             }
 
             window.addEventListener("popstate", (event) => updatePageState(event.state));
                     document.getElementById("logged-in-status").innerText = `Signed in as ${username}`;
                 }
             }
+
+            document.addEventListener("DOMContentLoaded", (event) => {
+                var mainDiv = document.getElementById("main");
+                var rootStyle = document.documentElement.style;
+                rootStyle.setProperty("--yellow", mainDiv.dataset.bgcolor);
+                rootStyle.setProperty("--black", mainDiv.dataset.fgcolor);
+                rootStyle.setProperty("--purple", mainDiv.dataset.accolor);
+
+                updateImageColors();
+            });
         </script>
     </head>
     <body>
 
             function updateImageColors() {
                 // Perform a palette swap on all gifs based on current page colors
-
                 document.querySelectorAll(".img-data").forEach(e => {
                     document.querySelectorAll(`.${e.id}`).forEach(t => {
                         t.src = customImage(e);
                     });
                 });
             }
-
-            // Update image colors on page load
-            document.addEventListener("DOMContentLoaded", updateImageColors);
-
         </script>
 
         <div class="page-header">
         {% endwith %}
 
         <!-- Page-Specific Content -->
-        <div class="main" id="main">
+        <div class="main" id="main" data-bgcolor="{{ bgcolor }}" data-fgcolor="{{ fgcolor }}" data-accolor="{{ accolor }}" data-username="{{ session['username'] }}">
         {% block body %}
         {% endblock %}
         </div>
diff --git a/templates/base.json b/templates/base.json
deleted file mode 100644 (file)
index c84d254..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "username": "{{ session['username'] }}",
-    "bgcolor": "{{ bgcolor }}",
-    "fgcolor": "{{ fgcolor }}",
-    "accolor": "{{ accolor }}",
-    "title": {{ dumps(self.title()) | safe }},
-    "body": {{ dumps(self.body()) | safe }}
-}
index 3ded208fa738b697551e28742d862cbf43b7d196..dc6cbb086cb140843099b00782e4c7cc6ed6bfad 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}Write a Comment{% endblock %}
 
index 8990e13d4350fb3fd601099a0877e821281a65ef..d8a20ec4fde640243a7469106a77c3b9171553e8 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}{% if song %}Edit Song{% else %}Upload Song{% endif %}{% endblock %}
 
@@ -61,7 +61,7 @@ Most standard audio/video formats are supported - .wav, .mp3, .ogg, .mp4, etc.
 
 <script>
 // Automatically set song name from file name
-document.getElementById("file-select").addEventListener("change", function(e) {
+document.getElementById("song-file").addEventListener("change", function(e) {
     var songTitle = document.getElementById("song-title");
     if (e.target.files[0] && !songTitle.value) {
         var name = e.target.files[0].name;
index 58a70fc9bf5a229161cee9f82cc9887b66f371c3..f04887acec58b51746ab149985e7b6ae7c9e5bef 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}Little Song Place{% endblock %}
 
index c7b19f9d4aa1c7b50e67a8483570e173219e6342..9c17e3950f054ca4615d11c318aba66bbcb1f738 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}Sign In{% endblock %}
 
index f8cdad870086ee0224e97a19e3f4522802c30efb..27da4fee4b1078ac8e3d79fdf31e5f97c85708c5 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}Site News{% endblock %}
 
index 2d2a1ed3ec349a76730bf9bac2e0f7f99df22c3d..8bc18687d819d49e85a11f3c008003cf56d77ea2 100644 (file)
@@ -1,19 +1,10 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}{{ name }}{% endblock %}
 
 {% block head -%}
 <meta property="og:title" content="{{ name }}" />
 <meta property="og:description" content="Playlist by {{ username }}" />
-<script>
-    // Apply user colors
-    document.addEventListener("DOMContentLoaded", (event) => {
-        var rootStyle = document.documentElement.style;
-        rootStyle.setProperty("--yellow", "{{ bgcolor }}");
-        rootStyle.setProperty("--black", "{{ fgcolor }}");
-        rootStyle.setProperty("--purple", "{{ accolor }}");
-    });
-</script>
 {%- endblock %}
 
 {% block body -%}
@@ -32,7 +23,7 @@ Playlist by <a href="/users/{{ username }}" class="profile-link">{{ username }}<
 {% if session["userid"] == userid -%}
 <p class="playlist-actions">
 <button class="button" onclick="showPlaylistEditor()">Edit</button>
-<button class="button" onclick="deletePlaylist()">Delete</button>
+<a href="/delete-playlist/{{ playlistid }}" class="button" onclick="return confirm('Are you sure you want to delete this playlist?')">Delete</a>
 </p>
 
 <script>
@@ -47,12 +38,6 @@ function hidePlaylistEditor() {
     document.querySelector(".playlist-actions").hidden = false;
     document.querySelector(".playlist-editor").hidden = true;
 }
-
-function deletePlaylist() {
-    if (confirm("Are you sure you want to delete this playlist?")) {
-        window.location.href = "/delete-playlist/{{ playlistid }}";
-    }
-}
 </script>
 
 {%- endif %}
index ee649ce50eed740222e9f2d0ad22246e41c09039..97874f1f328af4e79337aa34041df205b7df08bc 100644 (file)
@@ -1,24 +1,7 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}{{ name }}'s profile{% endblock %}
 
-{% block head %}
-<!-- Include coloris library for color picker -->
-<link rel="stylesheet" href="/static/coloris.min.css"/>
-<script src="/static/coloris.min.js"></script>
-
-<script>
-    // Apply user colors
-    document.addEventListener("DOMContentLoaded", (event) => {
-        var rootStyle = document.documentElement.style;
-        rootStyle.setProperty("--yellow", "{{ bgcolor }}");
-        rootStyle.setProperty("--black", "{{ fgcolor }}");
-        rootStyle.setProperty("--purple", "{{ accolor }}");
-    });
-</script>
-
-{% endblock %}
-
 {% block body %}
 
 <!-- Username -->
index 3dd4970f1437ec56f95cf47f07e34904b257fd43..09bd89369083c3025ac53108b528606da192300f 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}Create Account{% endblock %}
 
index 1bb003c221e3264c84825ae761c6679a074d2193..5581ca95d6a7f675405e59bb8050652b12707d11 100644 (file)
@@ -61,7 +61,7 @@
             <div class="song-playlist-controls">
                 <form action="/append-to-playlist" method="post">
                     <input type="hidden" name="songid" value="{{ song.songid }}" id="playlist-selector-songid"/>
-                    <select name="playlistid" onchange="this.closest('form').submit()">
+                    <select name="playlistid" onchange="this.closest('form').requestSubmit()">
                         <option value="-1">Add to Playlist...</option>
                         {% for plist in current_user_playlists -%}
                         <option value="{{ plist.playlistid }}">{{ plist['name'] }}</option>
index 411aae0d371bdf6105140fc84bbedd696b2aab2b..d993b91d7350852e464a9e11cd3247cefa662917 100644 (file)
@@ -1,17 +1,8 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block head %}
 <meta property="og:title" content="{{ song.title }}" />
 <meta property="og:description" content="Song by {{ song.username }}" />
-<script>
-    // Apply user colors
-    document.addEventListener("DOMContentLoaded", (event) => {
-        var rootStyle = document.documentElement.style;
-        rootStyle.setProperty("--yellow", "{{ bgcolor }}");
-        rootStyle.setProperty("--black", "{{ fgcolor }}");
-        rootStyle.setProperty("--purple", "{{ accolor }}");
-    });
-</script>
 {% endblock %}
 
 {% block title %}{{ song.title }}{% endblock %}
index 7d22e3376a6ab33093621bb29a14511adfbe3517..a8e3dbac7d0a7666f269be2dbd559632f710c3c7 100644 (file)
@@ -1,4 +1,4 @@
-{% if use_xml %}{% extends "base.xml" %}{% else %}{% extends "base.html" %}{% endif %}
+{% extends "base.html" %}
 
 {% block title %}Songs{% endblock %}