Subject: bug#69132: closed (Re: bug#69132: [ELPA] Remove jQuery from elpa.gnu.org)

From: [email-masked] (GNU bug Tracking System)
Date: Sat, 24 Feb 2024 10:05:02 +0000

Your bug report

#69132: [ELPA] Remove jQuery from elpa.gnu.org

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
69132: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=69132
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#69132: [ELPA] Remove jQuery from elpa.gnu.org
From: Philip Kaludercic <[email-masked]>
To: [email-masked]
Cc: Stefan Monnier <[email-masked]>
Date: Sat, 24 Feb 2024 10:03:34 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

Philip Kaludercic <[email-masked]> writes:

> I was recently surprised to see that elpa.gnu.org uses a jQuery library,
> where it really isn't necessary.  Re-implementing the same functionality
> can be done in a few more lines of plain Javascript, without the need
> for any minified code.  Tested with relatively recent versions of
> Firefox and Chromium, so perhaps it would be nice if someone with an
> older browser could check if I didn't make any bold assumptions. 

I have pushed updated versions of these patches to elpa.git, does the
same have to be done for nongnu.git?

Subject: [ELPA] Remove jQuery from elpa.gnu.org
From: Philip Kaludercic <[email-masked]>
To: [email-masked]
Date: Wed, 14 Feb 2024 19:41:50 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

I was recently surprised to see that elpa.gnu.org uses a jQuery library,
where it really isn't necessary.  Re-implementing the same functionality
can be done in a few more lines of plain Javascript, without the need
for any minified code.  Tested with relatively recent versions of
Firefox and Chromium, so perhaps it would be nice if someone with an
older browser could check if I didn't make any bold assumptions. 

>From 55766b2255e840824e7cd5156f625eba82896487 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <[email-masked]>
Date: Wed, 14 Feb 2024 20:05:09 +0100
Subject: [PATCH] Reimplement search without jQuery

---
 html/javascript/jquery.filtertable.min.js | 13 ----
 html/javascript/jquery.min.js             |  5 --
 html/javascript/package-search.js         | 39 ++++++++--
 html/layout.css                           | 92 ++++++-----------------
 4 files changed, 56 insertions(+), 93 deletions(-)
 delete mode 100644 html/javascript/jquery.filtertable.min.js
 delete mode 100644 html/javascript/jquery.min.js

diff --git a/html/javascript/jquery.filtertable.min.js b/html/javascript/jquery.filtertable.min.js
deleted file mode 100644
index b9e243d596..0000000000
--- a/html/javascript/jquery.filtertable.min.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * jquery.filterTable
- *
- * This plugin will add a search filter to tables. When typing in the filter,
- * any rows that do not contain the filter will be hidden.
- *
- * Utilizes bindWithDelay() if available. https://github.com/bgrins/bindWithDelay
- *
- * @version v1.5.7
- * @author Sunny Walker, [email-masked]
- * @license MIT
- */
\ No newline at end of file
diff --git a/html/javascript/jquery.min.js b/html/javascript/jquery.min.js
deleted file mode 100644
index e836475870..0000000000
--- a/html/javascript/jquery.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/*! jQuery v1.12.4 | (c) jQuery Foundation | jquery.org/license */
diff --git a/html/javascript/package-search.js b/html/javascript/package-search.js
index 47134045eb..92f29703a3 100644
--- a/html/javascript/package-search.js
+++ b/html/javascript/package-search.js
@@ -1,6 +1,35 @@
-$(document).ready(function() {
-	$('table').filterTable({
-		label: '',
-		placeholder: 'Search packages...'
-	});
+window.addEventListener("load", function (event) {
+	const table = document.getElementById("packages");
+
+	const search = document.createElement("input");
+	search.setAttribute("placeholder", "Search packages...");
+	search.setAttribute("type", "search");
+	search.addEventListener("input", function(event) {
+		const query = event.target.value;
+
+		for (let i = 1; i < table.rows.length; i++) {
+			const row = table.rows.item(i);
+			row.classList.remove("invisible");
+
+			const name = row.childNodes.item(0);
+			const name_match_p = name.innerText.match(query);
+			name.classList.remove("alt");
+
+			const desc = row.childNodes.item(2);
+			const desc_match_p = desc.innerText.match(query);
+			desc.classList.remove("alt");
+
+			if (query) { // avoid matching the empty string
+				if (name_match_p || desc_match_p) {
+					if (name_match_p) { name.classList.add("alt"); }
+					if (desc_match_p) { desc.classList.add("alt"); }
+				} else {
+					row.classList.add("invisible");
+				}
+			}
+		}
+	})
+
+	const main = document.querySelector("main");
+	main.prepend(search);
 });
diff --git a/html/layout.css b/html/layout.css
index 4f5c50d393..434220f8c1 100644
--- a/html/layout.css
+++ b/html/layout.css
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2022 Free Software Foundation, Inc.
+/* Copyright (C) 2010-2022, 2024 Free Software Foundation, Inc.
 
 This file is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -10,71 +10,23 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details. */
 
-/* Begin of reset */
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed, 
-figure, figcaption, footer, header, hgroup, 
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
-  margin: 0;
-  padding: 0;
-  border: 0;
-  font-size: 100%;
-  font: inherit;
-  vertical-align: baseline;
-}
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure, 
-footer, header, hgroup, menu, nav, section {
-  display: block;
-}
 body {
-  line-height: 1;
-}
-ol, ul {
-  list-style: none;
-}
-blockquote, q {
-  quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
-  content: '';
-  content: none;
-}
-table {
-  border-collapse: collapse;
-  border-spacing: 0;
-}
-
-/* End of reset */
-
-body {
-  font-family: "Fira Sans", sans-serif;
+  font-family: system-ui, sans-serif;
   line-height: 1.5em;
   font-size: 1.2em;
   color: #333;
 }
 
 html, body {
-  height: 100%;
+  height: 100vw;
 }
-.wrapper {
+#wrapper {
   min-height: 100%;
   height: auto !important; /* This line and the next line are not necessary unless you need IE6 support */
   height: 100%;
   margin: 0 auto -50px; /* the bottom margin is the negative value of the footer's height */
 }
-.footer, .push {
+footer, .push {
   height: 90px; /* .push must be the same height as .footer */
 }
 
@@ -196,13 +148,13 @@ dd {
   font-size: 1.2em;
 }
 
-.container {
+header, main, footer {
   padding: 20px;
   width: 960px;
   margin: 0 auto;
 }
 
-.header {
+header {
   color: white;
   text-align: center;
   background-color: #bb3955;
@@ -210,27 +162,27 @@ dd {
   border-bottom: 6px solid #691240;
 }
 
-.header p {
+header p {
   margin: 0;
 }
 
-.header a {
+header a {
   color: rgb(240, 255, 135);
   text-decoration: none;
 }
 
-.header a:hover {
+header a:hover {
   color: rgb(240, 255, 135);
   text-decoration: underline;
   background: transparent;
 }
 
-.header.small {
+header.small {
   text-align: left;
   border-width: 3px;
 }
 
-.header.small h1 {
+header.small h1 {
   display: inline;
   font-size: 1.5em;
   margin: 0;
@@ -239,7 +191,7 @@ dd {
   padding-left: 120px;
 }
 
-.header.small .container {
+header.small .container {
   padding: 20px;
 }
 
@@ -260,9 +212,13 @@ input[type="search"][placeholder] {
   color: #666;
 }
 
-.filter-table .quick { margin-left: 0.5em; font-size: 0.8em; text-decoration: none; }
-.fitler-table .quick:hover { text-decoration: underline; }
-td.alt { background-color: #ffc; background-color: rgba(255, 255, 0, 0.2); }
+tr.invisible {
+    display: none;
+}
+td.alt {
+    background-color: #ffc;
+    background-color: rgba(255, 255, 0, 0.2);
+}
 
 td, th {
   padding: 6px;
@@ -279,7 +235,7 @@ td {
   border-bottom: 1px solid #ddd;
 }
 
-.footer {
+footer {
   border-top: 1px solid #999;
   text-align:center;
   font-size: 0.9em;
@@ -287,11 +243,7 @@ td {
   color: #666;
 }
 
-.footer .container {
-  padding: 15px 0;
-}
-
-.footer p {
+footer p {
   margin: 0;
   font-size: .8em;
   padding: 0;
-- 
2.43.0

>From 73a9335634f54b71e9723047f327cf782cfb7244 Mon Sep 17 00:00:00 2001
From: Philip Kaludercic <[email-masked]>
Date: Wed, 14 Feb 2024 20:37:37 +0100
Subject: [PATCH] Update HTML generation for new filter implementation

---
 elpa-admin.el | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/elpa-admin.el b/elpa-admin.el
index 7831c794ae..f166c6f137 100644
--- a/elpa-admin.el
+++ b/elpa-admin.el
@@ -1553,24 +1553,19 @@ readme file has an unconventional name"
 
         <div class=\"wrapper\">
 
-            <div class=\"header small\">
-                <div class=\"container\">
+            <header class=\"small\">
                     <h1>%s</h1>
-                </div>
-            </div>
+            </header>
 
-            <div class=\"container\">\n"
+            <main>\n"
           title (or head-extra "") (or header title)))
 
 (defvar elpaa--index-javascript-headers "
-        <script src=\"../javascript/jquery.min.js\" type=\"text/javascript\"></script>
-        <script src=\"../javascript/jquery.filtertable.min.js\" type=\"text/javascript\"></script>
         <script src=\"../javascript/package-search.js\" type=\"text/javascript\"></script>")
 
 (defun elpaa--html-footer ()
   (format "\n
-        <div class=\"footer\">
-            <div class=\"container\">
+        <footer>
                 <p>Last refreshed on %s</p>
                 <p>Copyright 2016-%s <a href=\"https://fsf.org\">Free Software Foundation</a>, Inc.</p>
                 <p>Design provided by <a href=\"https://nicolas.petton.fr\">Nicolas Petton</a></p>
@@ -1580,8 +1575,7 @@ readme file has an unconventional name"
                   International License.
                 </p>
                 <p><a href=\"/jslicense.html\" data-jslicense=\"1\">JavaScript Licenses</a></p>
-            </div>
-        </div>
+        </footer>
 
 </body>\n"
           (format-time-string "%Y-%b-%d %R %Z" nil t)
@@ -1950,7 +1944,7 @@ arbitrary code."
                   "<div class=\"splice news\">\n"
                   (elpaa--section-to-html news)
                   "\n</div>\n")))
-      (insert "</div>\n")
+      (insert "</main>\n")
       (insert (elpaa--html-footer))
       (write-region (point-min) (point-max) (concat name ".html")))))
 
@@ -1959,15 +1953,16 @@ arbitrary code."
     (insert (elpaa--html-header
              (concat elpaa--name " ELPA Packages")
              nil elpaa--index-javascript-headers))
-    (insert "<table>\n")
-    (insert "<tr><th>Package</th><th>Version</th><th>Description</th></tr>\n")
+    (insert "<table id=\"packages\">\n")
+    (insert "<thead><tr><th>Package</th><th>Version</th><th>Description</th></tr></thead>\n")
+    (insert "<tbody>")
     (dolist (pkg pkgs)
       (insert (format "<tr><td><a href=\"%s.html\">%s</a></td><td>%s</td><td>%s</td></tr>\n"
                       (car pkg) (car pkg)
                       (package-version-join (aref (cdr pkg) 0))
                       (aref (cdr pkg) 2))))
-    (insert "                </table>
-            </div>
+    (insert "</tbody></table>
+            </main>
             <div class=\"push\"></div>
         </div>")
     (insert (elpaa--html-footer))
-- 
2.43.0