Hello,

As discussed at the GHM, please find attached revised patches for
list-packages.

The first patch tidies the CSS in (insert-css).

The second patch uses fold-values from (sxml fold) to achieve what my
previous patch did without the use of set! (essentially change the page
so that it does not assume JavaScript to display all content elegantly).

Output is visible at www.atheia.org/guix/list-packages.html again, and
it validates correctly.

Let me know if you spot any problems. I will have another go at
externalising the CSS and JS after these patches have been approved and
merged.

Best wishes,

Alex

>From 361b7aa0eff3681a8b0a47b7139fb7e84d7c8f71 Mon Sep 17 00:00:00 2001
From: Alex Sassmannshausen <alex.sassmannshau...@gmail.com>
Date: Mon, 26 Aug 2013 15:53:38 +0200
Subject: [PATCH 1/2] list-packages: Tidy CSS in preparation for split into
 external file.

* build-aux/list-packages.scm (insert-css): Tidy CSS alignment etc.
---
 build-aux/list-packages.scm |   97 ++++++++++++++++++++++++++++---------------
 1 file changed, 63 insertions(+), 34 deletions(-)

diff --git a/build-aux/list-packages.scm b/build-aux/list-packages.scm
index 9cb07c1..3e798fc 100755
--- a/build-aux/list-packages.scm
+++ b/build-aux/list-packages.scm
@@ -156,50 +156,79 @@ exec guile -l "$0"                              \
   "Return the CSS for the list-packages page."
   (format #t
 "<style>
-a {transition: all 0.3s}
-div#intro {margin-bottom: 5em}
-div#intro div, div#intro p {padding:0.5em}
-div#intro div {float:left}
-table#packages, table#packages tr, table#packages tbody, table#packages td,
-table#packages th {border: 0px solid black}
-div.package-description {position: relative}
-table#packages tr:nth-child(even) {background-color: #FFF}
-table#packages tr:nth-child(odd) {background-color: #EEE}
-table#packages tr:hover, table#packages tr:focus, table#packages tr:active {background-color: #DDD}
+/* license: CC0 */
+a {
+    transition: all 0.3s;
+}
+div#intro {
+    margin-bottom: 2em;
+}
+div#intro div, div#intro p {
+    padding:0.5em;
+}
+div#intro div {
+    float:left;
+}
+div#intro img {
+    float:left;
+    padding:0.75em;
+}
+table#packages, table#packages tr, table#packages tbody, table#packages td, table#packages th {
+    border: 0px solid black;
+    clear: both;
+}
+table#packages tr:nth-child(even) {
+    background-color: #FFF;
+}
+table#packages tr:nth-child(odd) {
+    background-color: #EEE;
+}
+table#packages tr:hover, table#packages tr:focus, table#packages tr:active {
+    background-color: #DDD;
+}
 table#packages tr:first-child, table#packages tr:first-child:hover, table#packages tr:first-child:focus, table#packages tr:first-child:active {
-background-color: #333;
-color: #fff;
+    background-color: #333;
+    color: #fff;
 }
-table#packages td
-{
-margin:0px;
-padding:0.2em 0.5em;
+table#packages td {
+    margin:0px;
+    padding:0.2em 0.5em;
 }
 table#packages td:first-child {
-width:10%;
-text-align:center;
+    width:10%;
+    text-align:center;
+}
+table#packages td:nth-child(2) {
+    width:30%;
+}
+table#packages td:last-child {
+    width:60%;
 }
-table#packages td:nth-child(2){width:30%;}
-table#packages td:last-child {width:60%}
 img.package-logo {
-float: left;
-padding-right: 1em;
+    float: left;
+    padding: 0.75em;
+}
+table#packages span {
+    font-weight: 700;
+}
+table#packages span a {
+    float: right;
+    font-weight: 500;
 }
-table#packages span a {float: right}
 a#top {
-position:fixed;
-right:2%;
-bottom:2%;
-font-size:150%;
-background-color:#EEE;
-padding:1.125% 0.75% 0% 0.75%;
-text-decoration:none;
-color:#000;
-border-radius:5px;
+    position:fixed;
+    right:10px;
+    bottom:10px;
+    font-size:150%;
+    background-color:#EEE;
+    padding:10px 7.5px 0 7.5px;
+    text-decoration:none;
+    color:#000;
+    border-radius:5px;
 }
 a#top:hover, a#top:focus {
-background-color:#333;
-color:#fff;
+    background-color:#333;
+    color:#fff;
 }
 </style>"))
 
-- 
1.7.10.4

>From ed5771c1d5a18c31634ef075d6fe1eee70b32d6b Mon Sep 17 00:00:00 2001
From: Alex Sassmannshausen <alex.sassmannshau...@gmail.com>
Date: Mon, 26 Aug 2013 15:55:28 +0200
Subject: [PATCH 2/2] list-packages: Progressive Enhancement approach to JS.

* build-aux/list-packages.scm (package->sxml): Modify formal params,
  docstring. Introduce logic for fold-values process.
  (insert-tr): Moved sxml package table-row generation to new function; remove
  <a> elements and JS function calls. These are created through JS
  (prep_pkg_descs). Add insert-js-call for every 15th package, and the last.
  (insert-js-call): New function.
  (packages->sxml): Change map to fold values; add init params.
  (insert-js): show_hide: add compatibility check, introduce, use thingLink
           prep: new JS function.
           bulk_show_hide: new JS function.
---
 build-aux/list-packages.scm |  133 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 101 insertions(+), 32 deletions(-)

diff --git a/build-aux/list-packages.scm b/build-aux/list-packages.scm
index 3e798fc..b32b595 100755
--- a/build-aux/list-packages.scm
+++ b/build-aux/list-packages.scm
@@ -29,6 +29,7 @@ exec guile -l "$0"                              \
   #:use-module (guix gnu-maintenance)
   #:use-module (gnu packages)
   #:use-module (sxml simple)
+  #:use-module (sxml fold)
   #:use-module (web uri)
   #:use-module (ice-9 match)
   #:use-module (srfi srfi-1)
@@ -48,8 +49,10 @@ exec guile -l "$0"                              \
               (equal? (gnu-package-name package) name))
             gnu))))
 
-(define (package->sxml package)
-  "Return HTML-as-SXML representing PACKAGE."
+(define (package->sxml package previous lid l)
+  "Return built HTML-as-SXML representing PACKAGEs, collected in
+PREVIOUS. Include a call to the JavaScript prep_pkg_descs function, every time
+the length of LID (increasing) is 15 or when L (decreasing) is 1."
   (define (source-url package)
     (let ((loc (package-location package)))
       (and loc
@@ -92,37 +95,72 @@ exec guile -l "$0"                              \
     (and=> (lookup-gnu-package name)
            gnu-package-logo))
 
+  (define (insert-tr description-id js?)
+    (define (insert-js-call lid)
+      "Return an sxml call to prep_pkg_descs, with up to 15 elements of lid as
+formal parameters."
+      (define (lid->js-argl)
+        "Parse a Scheme list into a JavaScript style arguments list."
+        (define (helper l)
+          (if (null? l)
+              ""                               ; No more args, done with list.
+              (string-append ", '" (car l) "'" ; Append a further arg.
+                             (helper (cdr l)))))
+
+        (string-append "'" (car lid) "'" ; Initial arg.
+                       (helper (cdr lid))))
+
+      `(script (@ (type "text/javascript")) ; Insert JS call
+               ,(format #f "prep_pkg_descs(~a)"
+                        (lid->js-argl))))
+
+    (let ((lid (cons description-id lid)))
+      `(tr (td ,(if (gnu-package? package)
+                    `(img (@ (src "/graphics/gnu-head-mini.png")
+                             (alt "Part of GNU")
+                             (title "Part of GNU")))
+                    ""))
+           (td (a (@ (href ,(source-url package))
+                     (title "Link to the Guix package source code"))
+                  ,(package-name package) " "
+                  ,(package-version package)))
+           (td (span ,(package-synopsis package))
+               (div (@ (id ,description-id))
+                    ,(match (package-logo (package-name package))
+                       ((? string? url)
+                        `(img (@ (src ,url)
+                                 (height "35")
+                                 (class "package-logo")
+                                 (alt ("Logo of " ,(package-name package))))))
+                       (_ #f))
+                    (p ,(package-description package))
+                    ,(license package)
+                    (a (@ (href ,(package-home-page package))
+                          (title "Link to the package's website"))
+                       ,(package-home-page package))
+                    ,(status package)
+                    ,(if js?
+                         (insert-js-call lid)
+                         ""))))))
+
   (let ((description-id (symbol->string
                          (gensym (package-name package)))))
-   `(tr (td ,(if (gnu-package? package)
-                 `(img (@ (src "/graphics/gnu-head-mini.png")
-                          (alt "Part of GNU")
-                          (title "Part of GNU")))
-                 ""))
-        (td (a (@ (href ,(source-url package))
-                  (title "Link to the Guix package source code"))
-               ,(package-name package) " "
-               ,(package-version package)))
-        (td (a (@ (href "javascript:void(0)")
-                  (title "show/hide package description")
-                  (onClick ,(format #f "javascript:show_hide('~a')"
-                                    description-id)))
-               ,(package-synopsis package))
-            (div (@ (id ,description-id)
-                    (style "display: none;"))
-                 ,(match (package-logo (package-name package))
-                    ((? string? url)
-                     `(img (@ (src ,url)
-                              (height "35")
-                              (class "package-logo")
-                              (alt ("Logo of " ,(package-name package))))))
-                    (_ #f))
-                 (p ,(package-description package))
-                 ,(license package)
-                 (a (@ (href ,(package-home-page package))
-                       (title "Link to the package's website"))
-                    ,(package-home-page package))
-                 ,(status package))))))
+    (cond ((= l 1)                               ; Last package in packages
+           (reverse                              ; Fold has reversed packages
+            (cons (insert-tr description-id 'js) ; Only return sxml
+                  previous)))
+          ((= (length lid) 15)          ; Time for a JS call
+           (values
+            (cons (insert-tr description-id 'js) ; Prefix new sxml
+                  previous)
+            '()                         ; Reset lid
+            (1- l)))                    ; Reduce l
+          (else                         ; Insert another row, and build lid
+           (values
+            (cons (insert-tr description-id #f) ; Prefix new sxml
+                  previous)
+            (cons description-id lid)   ; Pass along updated lid
+            (1- l))))))                 ; Reduce l
 
 (define (packages->sxml packages)
   "Return an HTML page as SXML describing PACKAGES."
@@ -145,7 +183,7 @@ exec guile -l "$0"                              \
            (tr (th "GNU?")
                (th "Package version")
                (th "Package details"))
-           ,@(map package->sxml packages))
+           ,@(fold-values package->sxml packages '() '() (length packages)))
     (a (@ (href "#intro")
           (title "Back to top.")
           (id "top"))
@@ -239,14 +277,45 @@ a#top:hover, a#top:focus {
 // license: CC0
 function show_hide(idThing)
 {
+  if(document.getElementById && document.createTextNode) {
     var thing = document.getElementById(idThing);
+    /* Used to change the link text, depending on whether description is
+       collapsed or expanded */
+    var thingLink = thing.previousSibling.lastChild.firstChild;
     if (thing) {
       if (thing.style.display == \"none\") {
         thing.style.display = \"\";
+        thingLink.data = 'Collapse';
       } else {
         thing.style.display = \"none\";
+        thingLink.data = 'Expand';
       }
     }
+  }
+}
+/* Add controllers used for collapse/expansion of package descriptions */
+function prep(idThing)
+{
+  var tdThing = document.getElementById(idThing).parentNode;
+  if (tdThing) {
+    var aThing = tdThing.firstChild.appendChild(document.createElement('a'));
+    aThing.setAttribute('href', 'javascript:void(0)');
+    aThing.setAttribute('title', 'show/hide package description');
+    aThing.appendChild(document.createTextNode('Expand'));
+    aThing.onclick=function(){show_hide(idThing);};
+    /* aThing.onkeypress=function(){show_hide(idThing);}; */
+  }
+}
+/* Take n element IDs, prepare them for javascript enhanced
+   display and hide the IDs by default. */
+function prep_pkg_descs()
+{
+  if(document.getElementById && document.createTextNode) {
+    for(var i=0; i<arguments.length; i++) {
+      prep(arguments[i])
+      show_hide(arguments[i]);
+    }
+  }
 }
 </script>"))
 
-- 
1.7.10.4

Reply via email to