list-packages: Progressive Enhancement approach to JS.

* build-aux/list-packages.scm (package->sxml): Add parameters previous,
  description-ids and remaining, update docstring accordingly. 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.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Alex Sassmannshausen 2013-09-22 15:43:23 +02:00 committed by Ludovic Courtès
parent 4fd6bf5337
commit a4141d6d53

@ -29,6 +29,7 @@ exec guile -l "$0" \
#:use-module (guix gnu-maintenance) #:use-module (guix gnu-maintenance)
#:use-module (gnu packages) #:use-module (gnu packages)
#:use-module (sxml simple) #:use-module (sxml simple)
#:use-module (sxml fold)
#:use-module (web uri) #:use-module (web uri)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
@ -48,8 +49,13 @@ exec guile -l "$0" \
(equal? (gnu-package-name package) name)) (equal? (gnu-package-name package) name))
gnu)))) gnu))))
(define (package->sxml package) (define (package->sxml package previous description-ids remaining)
"Return HTML-as-SXML representing PACKAGE." "Return 3 values: the HTML-as-SXML for PACKAGE added to all previously
collected package output in PREVIOUS, a list of DESCRIPTION-IDS and the number
of packages still to be processed in REMAINING. Also Introduces a call to the
JavaScript prep_pkg_descs function as part of the output of PACKAGE, every
time the length of DESCRIPTION-IDS, increasing, is 15 or when REMAINING,
decreasing, is 1."
(define (source-url package) (define (source-url package)
(let ((loc (package-location package))) (let ((loc (package-location package)))
(and loc (and loc
@ -92,37 +98,66 @@ exec guile -l "$0" \
(and=> (lookup-gnu-package name) (and=> (lookup-gnu-package name)
gnu-package-logo)) gnu-package-logo))
(define (insert-tr description-id js?)
(define (insert-js-call description-ids)
"Return an sxml call to prep_pkg_descs, with up to 15 elements of
description-ids as formal parameters."
`(script (@ (type "text/javascript"))
,(format #f "prep_pkg_descs(~a)"
(string-append "'"
(string-join description-ids "', '")
"'"))))
(let ((description-ids (cons description-id description-ids)))
`(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 description-ids)
""))))))
(let ((description-id (symbol->string (let ((description-id (symbol->string
(gensym (package-name package))))) (gensym (package-name package)))))
`(tr (td ,(if (gnu-package? package) (cond ((= remaining 1) ; Last package in packages
`(img (@ (src "/graphics/gnu-head-mini.png") (values
(alt "Part of GNU") (reverse ; Fold has reversed packages
(title "Part of GNU"))) (cons (insert-tr description-id 'js) ; Prefix final sxml
"")) previous))
(td (a (@ (href ,(source-url package)) '() ; No more work to do
(title "Link to the Guix package source code")) 0)) ; End of the line
,(package-name package) " " ((= (length description-ids) 15) ; Time for a JS call
,(package-version package))) (values
(td (a (@ (href "javascript:void(0)") (cons (insert-tr description-id 'js)
(title "show/hide package description") previous) ; Prefix new sxml
(onClick ,(format #f "javascript:show_hide('~a')" '() ; Reset description-ids
description-id))) (1- remaining))) ; Reduce remaining
,(package-synopsis package)) (else ; Insert another row, and build description-ids
(div (@ (id ,description-id) (values
(style "display: none;")) (cons (insert-tr description-id #f)
,(match (package-logo (package-name package)) previous) ; Prefix new sxml
((? string? url) (cons description-id description-ids) ; Update description-ids
`(img (@ (src ,url) (1- remaining)))))) ; Reduce remaining
(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))))))
(define (packages->sxml packages) (define (packages->sxml packages)
"Return an HTML page as SXML describing PACKAGES." "Return an HTML page as SXML describing PACKAGES."
@ -145,7 +180,7 @@ exec guile -l "$0" \
(tr (th "GNU?") (tr (th "GNU?")
(th "Package version") (th "Package version")
(th "Package details")) (th "Package details"))
,@(map package->sxml packages)) ,@(fold-values package->sxml packages '() '() (length packages)))
(a (@ (href "#intro") (a (@ (href "#intro")
(title "Back to top.") (title "Back to top.")
(id "top")) (id "top"))
@ -239,14 +274,45 @@ a#top:hover, a#top:focus {
// license: CC0 // license: CC0
function show_hide(idThing) function show_hide(idThing)
{ {
if(document.getElementById && document.createTextNode) {
var thing = document.getElementById(idThing); 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) {
if (thing.style.display == \"none\") { if (thing.style.display == \"none\") {
thing.style.display = \"\"; thing.style.display = \"\";
thingLink.data = 'Collapse';
} else { } else {
thing.style.display = \"none\"; 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>")) </script>"))