PageSourceSearch

https://todae.com.au/assets/ui.js?v=7b31d95d

js todae.com.au collected 2026-10-03 22:09:32 UTC 4,610 bytes, 132 lines download raw bytes

1/* Mobile navigation.
2   Builds a real hamburger menu from the markup already on the page, so the
3   header stays short on a phone and every link is a proper tap target.
4
5   Progressive enhancement: without JavaScript the nav renders as a plain list
6   of links, which still works. The toggle only appears once this runs. */
7
8(function () {
9  'use strict';
10
11  var BREAKPOINT = 860;
12  var head = document.querySelector('.site-head');
13  if (!head) return;
14
15  var nav = head.querySelector('.nav');
16  if (!nav) return;
17
18  var subnav = document.querySelector('.subnav');
19  var panel, toggle, lastFocus;
20
21  function buildToggle() {
22    toggle = document.createElement('button');
23    toggle.className = 'navtoggle';
24    toggle.type = 'button';
25    toggle.setAttribute('aria-expanded', 'false');
26    toggle.setAttribute('aria-controls', 'primary-nav');
27    toggle.setAttribute('aria-label', 'Open menu');
28    toggle.innerHTML = '<span class="navtoggle-bars" aria-hidden="true"><i></i><i></i><i></i></span>' +
29                       '<span class="navtoggle-text">Menu</span>';
30    var brand = head.querySelector('.brand');
31    var row = head.querySelector('.head-in') || head;
32    if (brand && brand.parentNode === row) { row.insertBefore(toggle, brand.nextSibling); }
33    else { row.appendChild(toggle); }
34  }
35
36  function buildPanel() {
37    panel = document.createElement('div');
38    panel.className = 'navpanel';
39    panel.id = 'primary-nav';
40
41    // the primary links, moved (not copied) so there is one set in the DOM
42    var primary = document.createElement('div');
43    primary.className = 'navpanel-primary';
44    primary.appendChild(nav);
45    panel.appendChild(primary);
46
47    // the category rail, mirrored into the panel so everything is in one place
48    if (subnav) {
49      var links = subnav.querySelectorAll('a');
50      if (links.length) {
51        var wrap = document.createElement('div');
52        wrap.className = 'navpanel-cats';
53        var heading = document.createElement('p');
54        heading.className = 'navpanel-heading';
55        heading.textContent = 'Sections';
56        wrap.appendChild(heading);
57        var list = document.createElement('ul');
58        Array.prototype.forEach.call(links, function (a) {
59          var li = document.createElement('li');
60          var copy = document.createElement('a');
61          copy.href = a.getAttribute('href');
62          copy.textContent = a.textContent;
63          li.appendChild(copy);
64          list.appendChild(li);
65        });
66        wrap.appendChild(list);
67        panel.appendChild(wrap);
68      }
69    }
70
71    head.appendChild(panel);
72  }
73
74  function open() {
75    lastFocus = document.activeElement;
76    head.classList.add('nav-open');
77    document.body.classList.add('nav-locked');
78    toggle.setAttribute('aria-expanded', 'true');
79    toggle.setAttribute('aria-label', 'Close menu');
80    var first = panel.querySelector('a');
81    if (first) first.focus();
82  }
83
84  function close(returnFocus) {
85    head.classList.remove('nav-open');
86    document.body.classList.remove('nav-locked');
87    toggle.setAttribute('aria-expanded', 'false');
88    toggle.setAttribute('aria-label', 'Open menu');
89    if (returnFocus && lastFocus && lastFocus.focus) lastFocus.focus();
90  }
91
92  function isOpen() { return head.classList.contains('nav-open'); }
93
94  function wire() {
95    toggle.addEventListener('click', function () {
96      isOpen() ? close(true) : open();
97    });
98
99    // a link inside the panel navigates, so close behind it
100    panel.addEventListener('click', function (ev) {
101      if (ev.target.closest('a')) close(false);
102    });
103
104    document.addEventListener('keydown', function (ev) {
105      if (ev.key === 'Escape' && isOpen()) close(true);
106    });
107
108    // keep focus inside the panel while it is open
109    panel.addEventListener('keydown', function (ev) {
110      if (ev.key !== 'Tab' || !isOpen()) return;
111      var items = panel.querySelectorAll('a, button');
112      if (!items.length) return;
113      var first = items[0], last = items[items.length - 1];
114      if (ev.shiftKey && document.activeElement === first) { ev.preventDefault(); last.focus(); }
115      else if (!ev.shiftKey && document.activeElement === last) { ev.preventDefault(); toggle.focus(); }
116    });
117
118    // a rotation back to desktop must not leave the page stuck behind a panel
119    var timer;
120    window.addEventListener('resize', function () {
121      clearTimeout(timer);
122      timer = setTimeout(function () {
123        if (window.innerWidth > BREAKPOINT && isOpen()) close(false);
124      }, 150);
125    });
126  }
127
128  buildToggle();
129  buildPanel();
130  wire();
131  head.classList.add('has-toggle');
132})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.