Fossil

Check-in [e3376829]
Login

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

Overview
Comment:Switch away from classic (bubbling-only) event handling to simplify management of temporary handlers, and to have the ESC key listener use a priority (capturing) handler, to prevent any other keydown handlers or default actions for the ESC key while the panel is open. This does not change the compatibility test results summarized here: https://fossil-scm.org/forum/forumpost/f425a1756c. (IE8 halts JS processing at JSON.parse in antiRobotDefense, anyway.) Also, for non-compatible browsers, there's a new fallback to transform the hamburger button into a simple (non-scripted) link to the sitemap.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | js-hamburger-menu
Files: files | file ages | folders
SHA1:e3376829e211a3f2d4fc566619423a307b6d23b0
User & Date: florian 2018-10-12 16:16:55
Context
2018-10-12
16:18
For consistency, HTMLize another TH1 variable, though not sure if this is required, see https://fossil-scm.org/forum/forumpost/bc0b6ce4a1. check-in: 5677271a user: florian tags: js-hamburger-menu
16:16
Switch away from classic (bubbling-only) event handling to simplify management of temporary handlers, and to have the ESC key listener use a priority (capturing) handler, to prevent any other keydown handlers or default actions for the ESC key while the panel is open. This does not change the compatibility test results summarized here: https://fossil-scm.org/forum/forumpost/f425a1756c. (IE8 halts JS processing at JSON.parse in antiRobotDefense, anyway.) Also, for non-compatible browsers, there's a new fallback to transform the hamburger button into a simple (non-scripted) link to the sitemap. check-in: e3376829 user: florian tags: js-hamburger-menu
2018-10-11
16:36
Cancel the timer to remove the border of the hamburger menu panel after the closing animation, if the menu is closed and immediately reopened by double-clicking the hamburger button. check-in: c73deeb6 user: florian tags: js-hamburger-menu
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to skins/default/js.txt.

14
15
16
17
18
19
20

21





22
23
24
25
26
27
28
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
...
102
103
104
105
106
107
108
109



110
111
112
113

114
115
116
117

118
119
120



121
122
123
124
125
126
127
128
129
130
131
132
...
144
145
146
147
148
149
150
151
152
153
154
155

156
157
158
159
160

161
162
163
164
165
166

167
168
169


170
171
172
173


174
175
176
177
178
179
180
*******************************************************************************
**
** This file contains the JS code specific to the Fossil default skin.
** Currently, the only thing this does is handle clicks on its hamburger
** menu button.
*/
(function() {

  if (!document.getElementById("hbbtn")) return;   // no hamburger button





  var panel = document.getElementById("hbdrop");
  if (!panel) return;   // site admin might've nuked it
  if (!panel.style) return;  // shouldn't happen, but be sure
  var panelBorder = panel.style.border;
  var panelInitialized = false;   // reset if browser window is resized
  var panelResetBorderTimerID = 0;   // used to cancel post-animation tasks

................................................................................
  // header.txt by setting the "data-anim-ms" attribute of the panel.
  var animMS = panel.getAttribute("data-anim-ms");
  if (animMS === "0")
    animate = false;   // disable animation if "data-anim-ms" === "0"
  else if (!animMS || animMS>>0 !== Number(animMS) || animMS < 0)
    animMS = 400;   // set default if missing, empty, non-integer, or negative

  var originalEventHandlers = { };   // original event handlers to be restored

  // Calculate panel height despite its being hidden at call time.
  // Based on https://stackoverflow.com/a/29047447/142454
  var panelHeight;  // computed on first panel display
  function calculatePanelHeight() {

    // Clear the max-height CSS property in case the panel size is recalculated
    // after the browser window was resized.
................................................................................
      }
      setTimeout(function() {
        panel.style.maxHeight = panelHeight;
        panel.style.border    = panelBorder;
      }, 40);   // 25ms is insufficient with Firefox 62
    }
    panel.style.display = 'block';
    originalEventHandlers.onkeydown = document.onkeydown;



    document.onkeydown = function(event) {
      event = event || window.event;
      var key = event.which || event.keyCode;
      if (key == 27) {

        panelToggle(true);
      }
    };
    originalEventHandlers.onclick = document.onclick;

    document.onclick = function(event) {
      event = event || window.event;
      if (!panel.contains(event.target)) {



        panelToggle(true);
        //return false;   // prevent default action (i.e. open clicked links)
      }
    };
  }

  // Return true if the panel is showing.
  function panelShowing() {
    if (animate) {
      return panel.style.maxHeight == panelHeight;
    }
    else {
................................................................................
      childElement = childElement.nextSibling;
    }
    return false;
  }

  // Reset the state of the panel to uninitialized if the browser window is
  // resized, so the dimensions are recalculated the next time it's opened.
  originalEventHandlers.onresize = window.onresize;
  window.onresize = function(event) {
    panelInitialized = false;
    if (originalEventHandlers.onresize) {
      originalEventHandlers.onresize.call(window,event);

    }
  };

  // Click handler for the hamburger button.
  document.getElementById("hbbtn").onclick = function(event) {

    // Break the event handler chain, or the handler for document.onclick
    // (about to be installed) may already be triggered by the current event.
    if (event.stopPropagation)
      event.stopPropagation();
    else
      event.cancelBubble = true;

    panelToggle(false);
    return false;  // prevent browser from acting on <a> click
  };


  function panelToggle(suppressAnimation) {
    if (panelShowing()) {
      document.onkeydown = originalEventHandlers.onkeydown;
      document.onclick = originalEventHandlers.onclick;


      // Transition back to hidden state.
      if (animate) {
        if (suppressAnimation) {
          var transition = panel.style.transition;
          panel.style.transition = '';
          panel.style.maxHeight = '0';
          panel.style.border = 'none';







>
|
>
>
>
>
>







 







<
<







 







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







 







<
|

<
<
>
|
<
<

<
>
|

<
|
<
<
>

<
<
>
>


<
<
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
43
44
45
46
47
48
49


50
51
52
53
54
55
56
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132

133
134

135
136
137
138
139
140
141
...
153
154
155
156
157
158
159

160
161


162
163


164

165
166
167

168


169
170


171
172
173
174


175
176
177
178
179
180
181
182
183
*******************************************************************************
**
** This file contains the JS code specific to the Fossil default skin.
** Currently, the only thing this does is handle clicks on its hamburger
** menu button.
*/
(function() {
  var hbButton = document.getElementById("hbbtn");
  if (!hbButton) return;   // no hamburger button
  if (!document.addEventListener) {
    // Turn the button into a link to the sitemap for incompatible browsers.
    hbButton.href = "$home/sitemap";
    return;
  }
  var panel = document.getElementById("hbdrop");
  if (!panel) return;   // site admin might've nuked it
  if (!panel.style) return;  // shouldn't happen, but be sure
  var panelBorder = panel.style.border;
  var panelInitialized = false;   // reset if browser window is resized
  var panelResetBorderTimerID = 0;   // used to cancel post-animation tasks

................................................................................
  // header.txt by setting the "data-anim-ms" attribute of the panel.
  var animMS = panel.getAttribute("data-anim-ms");
  if (animMS === "0")
    animate = false;   // disable animation if "data-anim-ms" === "0"
  else if (!animMS || animMS>>0 !== Number(animMS) || animMS < 0)
    animMS = 400;   // set default if missing, empty, non-integer, or negative



  // Calculate panel height despite its being hidden at call time.
  // Based on https://stackoverflow.com/a/29047447/142454
  var panelHeight;  // computed on first panel display
  function calculatePanelHeight() {

    // Clear the max-height CSS property in case the panel size is recalculated
    // after the browser window was resized.
................................................................................
      }
      setTimeout(function() {
        panel.style.maxHeight = panelHeight;
        panel.style.border    = panelBorder;
      }, 40);   // 25ms is insufficient with Firefox 62
    }
    panel.style.display = 'block';
    document.addEventListener('keydown',panelKeydown,/* useCapture == */true);
    document.addEventListener('click',panelClick,false);
  }

  var panelKeydown = function(event) {
    event = event || window.event;
    var key = event.which || event.keyCode;
    if (key == 27) {
      event.stopPropagation();   // ignore other keydown handlers
      panelToggle(true);
    }
  };


  var panelClick = function(event) {
    event = event || window.event;
    if (!panel.contains(event.target)) {
      // Call event.preventDefault() to have clicks outside the opened panel
      // just close the panel, and swallow clicks on links or form elements.
      //event.preventDefault();
      panelToggle(true);

    }
  };


  // Return true if the panel is showing.
  function panelShowing() {
    if (animate) {
      return panel.style.maxHeight == panelHeight;
    }
    else {
................................................................................
      childElement = childElement.nextSibling;
    }
    return false;
  }

  // Reset the state of the panel to uninitialized if the browser window is
  // resized, so the dimensions are recalculated the next time it's opened.

  window.addEventListener('resize',function(event) {
    panelInitialized = false;


  },false);



  // Click handler for the hamburger button.

  hbButton.addEventListener('click',function(event) {
    // Break the event handler chain, or the handler for documentclick
    // (about to be installed) may already be triggered by the current event.

    event.stopPropagation();


    event.preventDefault();  // prevent browser from acting on <a> click
    panelToggle(false);


  },false);

  function panelToggle(suppressAnimation) {
    if (panelShowing()) {


      document.removeEventListener('keydown',panelKeydown,/* useCapture == */true);
      document.removeEventListener('click',panelClick,false);
      // Transition back to hidden state.
      if (animate) {
        if (suppressAnimation) {
          var transition = panel.style.transition;
          panel.style.transition = '';
          panel.style.maxHeight = '0';
          panel.style.border = 'none';