www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

spoiler1.rkt (4423B)


      1 #lang racket
      2 
      3 (provide spoiler-wrapper-collapsed
      4          spoiler-default
      5          spoiler-alt
      6          spoiler-button-default-to-alt
      7          spoiler-button-alt-to-default
      8          spoiler1
      9          spler)
     10 
     11 (require scribble/manual
     12          scribble/core
     13          scribble/decode
     14          scribble/html-properties
     15          hyper-literate
     16          (for-syntax syntax/parse)
     17          scriblib/render-cond)
     18 
     19 (define spoiler-css
     20   #"
     21 .spoiler-wrapper-expanded .spoiler-default,
     22 .spoiler-wrapper-expanded .spoiler-button-default-to-alt {
     23   display:none;
     24 }
     25 .spoiler-wrapper-collapsed .spoiler-alt,
     26 .spoiler-wrapper-collapsed .spoiler-button-alt-to-default {
     27   display:none;
     28 }
     29 
     30 .spoiler-button-default-to-alt,
     31 .spoiler-button-alt-to-default {
     32   color: #2a657e;
     33 }
     34 ")
     35 
     36 (define spoiler-js
     37   (string->bytes/utf-8
     38    #<<EOJS
     39 function toggleSpoiler(e, doExpand) {
     40  var expanded = function(className) {
     41    return className.match(/\bspoiler-wrapper-expanded\b/);
     42   };
     43   var collapsed = function(className) {
     44     return className.match(/\bspoiler-wrapper-collapsed\b/);
     45   };
     46   var found = function(className) {
     47     return expanded(className) || collapsed(className);
     48   };
     49   var wrapper = e;
     50   while (e != document && e != null && ! found(e.className)) {
     51     e = e.parentNode;
     52   }
     53   e.className = e
     54                 .className
     55                 .replace(/  */g, " ")
     56                 .replace(/\bspoiler-wrapper-expanded\b/, '')
     57                 .replace(/\bspoiler-wrapper-collapsed\b/, '');
     58   if (doExpand) {
     59     e.className = e.className + " spoiler-wrapper-expanded";
     60   } else {
     61     e.className = e.className + " spoiler-wrapper-collapsed";
     62   }
     63   if (e.preventDefault) { e.preventDefault(); }
     64   return false;
     65 }
     66 EOJS
     67    ))
     68 
     69 (define-syntax-rule (def-style name)
     70   (define name
     71     (style (symbol->string 'name)
     72            (list (css-addition spoiler-css)
     73                  (js-addition spoiler-js)
     74                  (alt-tag "div")))))
     75 
     76 (def-style spoiler-wrapper-collapsed)
     77 (def-style spoiler-default)
     78 (def-style spoiler-alt)
     79 
     80 (define (spoiler-button-default-to-alt txt)
     81   (hyperlink
     82    #:style (style "spoiler-button-default-to-alt"
     83                   (list (css-addition spoiler-css)
     84                         (js-addition spoiler-js)
     85                         (attributes
     86                          '([onclick . "return toggleSpoiler(this, true);"]))))
     87    "#"
     88    txt))
     89 
     90 (define (spoiler-button-alt-to-default txt)
     91   (hyperlink
     92    #:style (style "spoiler-button-alt-to-default"
     93                   (list (css-addition spoiler-css)
     94                         (js-addition spoiler-js)
     95                         (attributes
     96                          '([onclick . "return toggleSpoiler(this, false);"]))))
     97    "#"
     98    txt))
     99 
    100 (define (spoiler1 default button-default→alt button-alt→default alternate)
    101   (nested-flow spoiler-wrapper-collapsed
    102                (list
    103                 (paragraph (style #f '())
    104                            (spoiler-button-default-to-alt button-default→alt))
    105                 (nested-flow spoiler-default
    106                              (decode-flow default))
    107                 (paragraph (style #f '())
    108                            (spoiler-button-alt-to-default button-alt→default))
    109                 (nested-flow spoiler-alt
    110                              (decode-flow alternate)))))
    111 
    112 (define-syntax spler
    113   (syntax-parser
    114     [(_ name default ... #:expanded expanded ...)
    115      #'(begin
    116          (chunk #:save-as ck1
    117                 #:display-only
    118                 #:button
    119                 (cond-element
    120                  [html (list " " (smaller
    121                                   (spoiler-button-default-to-alt "expand")))]
    122                  [else (list)])
    123                 name
    124                 default ...)
    125 
    126          (chunk #:save-as ck2
    127                 #:button
    128                 (cond-element
    129                  [html (list " " (smaller
    130                                   (spoiler-button-alt-to-default "collapse")))]
    131                  [else (list)])
    132                 name
    133                 expanded ...)
    134 
    135          (cond-block
    136           [html (nested-flow spoiler-wrapper-collapsed
    137                              (list (nested-flow spoiler-default
    138                                                 (decode-flow (ck1)))
    139                                    (nested-flow spoiler-alt
    140                                                 (decode-flow (ck2)))))]
    141           [else (nested-flow (style #f '())
    142                              (decode-flow (ck2)))]))]))