Fossil

Check-in [90bd6675]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Using CSS transitions to mimic jQuery's slideUp/Down() transitions. This probably restricts browser compatibility still further above the XHR issue noted in the earlier checkin on this branch. According to MDN, we're probably restricted to IE 10+ with this, and maybe not even that due to not using vendor-specific extensions for the transitional browser versions.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | js-hamburger-menu
Files: files | file ages | folders
SHA3-256:90bd66750d539aebc817f906fe8b75dfcf72c4603ec14fbf8b80acf6095773e2
User & Date: wyoung 2018-09-10 08:48:34
Context
2018-09-10
09:02
Increased the transition delay to make the initial drop-down animation happen in Firefox 62. check-in: 8918a8a8 user: wyoung tags: js-hamburger-menu
08:48
Using CSS transitions to mimic jQuery's slideUp/Down() transitions. This probably restricts browser compatibility still further above the XHR issue noted in the earlier checkin on this branch. According to MDN, we're probably restricted to IE 10+ with this, and maybe not even that due to not using vendor-specific extensions for the transitional browser versions. check-in: 90bd6675 user: wyoung tags: js-hamburger-menu
07:17
Converted JS hamburger button menu code to use standard JS only, no jQuery.

Temporarily lost the animation with this change: I'm checking this in separately to make the difference between this and the jQuery version clearer.

Not sure how portable it is yet; I wouldn't be surprised if it broke on old IE, since we're using xhr.onload instead of the horrid mess that is xhr.onreadystatechange. check-in: 113ba3d9 user: wyoung tags: js-hamburger-menu

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to skins/default/footer.txt.

5
6
7
8
9
10
11

12
13

















14


15












16
17


18
19

20
21
22
23
24







25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40












41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
</div>

<th1>
  html "<script nonce='$nonce'>"
  html "  (function() { var home='$home'; "
</th1>
    var panel = document.getElementById("hbdrop");


    panel.onclick = panel.hide = function() {

















      panel.style.display = 'none';


    }












    panel.show = function() {
      panel.style.display = 'block';


    }


    var needSitemapHTML = true;
    document.querySelector("div.mainmenu > a").onclick = function() {
      if (panel.style.display == 'block') {
        // Hamburger button clicked a second time.
        panel.hide();







      }
      else if (needSitemapHTML) {
        // Only get it once per page load: it isn't likely to
        // change on us.
        var xhr = new XMLHttpRequest();
        xhr.onload = function() {
          var doc = xhr.responseXML;
          if (doc) {
            var sm = doc.querySelector("ul#sitemap");
            if (sm && xhr.status == 200) {

              needSitemapHTML = false;
              panel.innerHTML = sm.outerHTML;
              if (window.setAllHrefs) {
                setAllHrefs();   // don't need anti-robot defense here
              }
              panel.show();












            }
          }
          // else, can't parse response as HTML or XML
        }
        xhr.open("GET", home + "/sitemap");
        xhr.responseType = "document";
        xhr.send();
      }
      else {
        panel.show();   // just show what we built above
      }
      return false;  // prevent browser from acting on <a> click
    }
  })();
</script>







>

<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>


>


|
|
<
>
>
>
>
>
>
>










>





<
>
>
>
>
>
>
>
>
>
>
>
>









|





5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
</div>

<th1>
  html "<script nonce='$nonce'>"
  html "  (function() { var home='$home'; "
</th1>
    var panel = document.getElementById("hbdrop");
    var panelBorder = panel.style.border;


    // Calculate panel height despite its being hidden at call time.
    // Based on https://stackoverflow.com/a/29047447/142454
    var panelHeight;  // computed on sitemap load
    function calculatePanelHeight() {
      // Get initial panel styles so we can restore them below.
      var es   = window.getComputedStyle(panel),
          edis = es.display,
          epos = es.position,
          evis = es.visibility;

      // Restyle the panel so we can measure its height while invisible.
      panel.style.visibility = 'hidden';
      panel.style.position   = 'absolute';
      panel.style.display    = 'block';
      panelHeight = panel.offsetHeight + 'px';

      // Revert styles now that job is done.
      panel.style.display    = edis;
      panel.style.position   = epos;
      panel.style.visibility = evis;
    }

    // Show the panel by changing the panel height, which kicks off the
    // slide-open/closed transition set up in the XHR onload handler.
    //
    // Schedule the change for a near-future time in case this is the
    // first call, where the div was initially invisible.  That causes
    // the browser to consider the height change as part of the same
    // state change as the visibility change, so it doesn't see a state
    // *transition*, hence never kicks off the *CSS* transition:
    //
    // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#JavaScript_examples
    function showPanel() {
      setTimeout(function() {
        panel.style.maxHeight = panelHeight;
        panel.style.border    = panelBorder;
      }, 10);
    }

    // Click handler for the hamburger button.
    var needSitemapHTML = true;
    document.querySelector("div.mainmenu > a").onclick = function() {
      if (panel.style.maxHeight == panelHeight) {
        // Hamburger button clicked while panel visible.  Trigger the

        // transition back to hidden state.
        panel.style.maxHeight = '0';
        setTimeout(function() {
          // Browsers show a 1px high line when maxHeight == 0, so
          // temporarily hide the borders while hidden.
          panel.style.border = 'none';
        }, 300);
      }
      else if (needSitemapHTML) {
        // Only get it once per page load: it isn't likely to
        // change on us.
        var xhr = new XMLHttpRequest();
        xhr.onload = function() {
          var doc = xhr.responseXML;
          if (doc) {
            var sm = doc.querySelector("ul#sitemap");
            if (sm && xhr.status == 200) {
              // Got sitemap.  Insert it into the drop-down panel.
              needSitemapHTML = false;
              panel.innerHTML = sm.outerHTML;
              if (window.setAllHrefs) {
                setAllHrefs();   // don't need anti-robot defense here
              }


              // Set up the CSS transition to animate the panel open and
              // closed.  Only needs to be done once per page load.
              // Based on https://stackoverflow.com/a/29047447/142454
              calculatePanelHeight();
              panel.style.transition = 'max-height 0.5s ease-in-out';
              panel.style.overflowY  = 'hidden';
              panel.style.maxHeight  = '0';
              panel.style.display    = 'block';

              // Kick off the transition
              showPanel();
            }
          }
          // else, can't parse response as HTML or XML
        }
        xhr.open("GET", home + "/sitemap");
        xhr.responseType = "document";
        xhr.send();
      }
      else {
        showPanel();   // just show what we built above
      }
      return false;  // prevent browser from acting on <a> click
    }
  })();
</script>