1/* The connection page. 2 * 3 * There is no HTTP status for a dropped connection, so nothing on the server can serve this one. 4 * It is drawn here, when a reader who is already on the site tries to go somewhere and cannot. 5 * 6 * Deliberately not a service worker. A reader arriving cold with no network gets the browser's own 7 * error, because nothing of ours is cached â that case was ruled out: this is for losing the 8 * connection mid-visit, which is the one a person actually meets. 9 */ 10(function () { 11 'use strict'; 12 13 var boot = window.CIL_ERROR_OFFLINE; 14 if (!boot) return; 15 16 var overlay = null; 17 18 function offline() { 19 // navigator.onLine only ever tells the truth when it says false: a machine on a network 20 // that cannot reach anything still reports true. False is enough for what this catches. 21 return navigator.onLine === false; 22 } 23 24 function build() { 25 if (overlay) return overlay; 26 27 overlay = document.createElement('div'); 28 overlay.className = 'cil-error cil-error--overlay'; 29 overlay.setAttribute('role', 'alert'); 30 overlay.setAttribute('data-error-kind', 'offline'); 31 32 var column = document.createElement('div'); 33 column.className = 'cil-error__column'; 34 35 var title = document.createElement('h1'); 36 title.className = 'cil-error__title'; 37 title.textContent = boot.title; 38 39 var lead = document.createElement('p'); 40 lead.className = 'cil-error__lead'; 41 lead.textContent = boot.description; 42 43 var actions = document.createElement('div'); 44 actions.className = 'cil-error__actions'; 45 46 // The same button the other three pages carry: the house bubble gesture, with the look 47 // worked out server-side and sent along. An editor who removed the button from this page 48 // gets no button here either. 49 if (boot.button) { 50 var retry = document.createElement('button'); 51 retry.type = 'button'; 52 retry.className = 'cil-bubble-btn ' + boot.button.class; 53 retry.setAttribute('style', boot.button.style); 54 55 for (var i = 0; i < 4; i++) { 56 var bubble = document.createElement('span'); 57 bubble.className = 'cil-bubble-btn__bubble'; 58 bubble.setAttribute('aria-hidden', 'true'); 59 retry.appendChild(bubble); 60 } 61 62 var label = document.createElement('span'); 63 label.className = 'cil-bubble-btn__label'; 64 label.textContent = boot.retry; 65 retry.appendChild(label); 66 67 retry.addEventListener('click', function () { 68 if (offline()) return; // still nothing to load; leave the page where it is 69 window.location.reload(); 70 }); 71 72 actions.appendChild(retry); 73 } 74 column.appendChild(title); 75 column.appendChild(lead); 76 column.appendChild(actions); 77 overlay.appendChild(column); 78 79 // The scene is decorative and the markup for it is the renderer's; the overlay borrows the 80 // same classes so the two pages cannot drift apart visually. 81 var scene = document.createElement('div'); 82 scene.className = 'cil-error__scene'; 83 scene.setAttribute('aria-hidden', 'true'); 84 ['ring--blue', 'ring--yellow', 'ring--green', 'bar--green', 'bar--yellow', 'bar--red', 85 'dot--red', 'dot--green', 'dot--blue'].forEach(function (part) { 86 var el = document.createElement('span'); 87 el.className = 'cil-error__' + part.split('--')[0] + ' cil-error__' + part; 88 scene.appendChild(el); 89 }); 90 overlay.insertBefore(scene, column); 91 92 return overlay; 93 } 94 95 function show() { 96 var el = build(); 97 if (el.isConnected) return; 98 document.body.appendChild(el); 99 document.body.classList.add('cil-error-offline'); 100 var cta = el.querySelector('.cil-error__cta'); 101 if (cta) cta.focus(); 102 } 103 104 function hide() { 105 if (overlay && overlay.isConnected) overlay.remove(); 106 document.body.classList.remove('cil-error-offline'); 107 } 108 109 /* A link followed while the connection is down would land on the browser's own error page, and 110 the reader would lose the site. Caught here instead, so they stay where they are. */ 111 document.addEventListener('click', function (e) { 112 if (!offline()) return; 113 114 var link = e.target.closest ? e.target.closest('a[href]') : null; 115 if (!link) return; 116 117 var href = link.getAttribute('href') || ''; 118 // Anything that does not leave the page is none of this listener's business. 119 if (!href || href.charAt(0) === '#' || /^(mailto:|tel:|javascript:)/i.test(href)) return; 120 if (link.target && link.target !== '_self') return; 121 if (link.hasAttribute('download')) return; 122 123 e.preventDefault(); 124 show(); 125 }, true); 126 127 document.addEventListener('submit', function (e) { 128 if (!offline()) return; 129 e.preventDefault(); 130 show(); 131 }, true); 132 133 window.addEventListener('online', hide); 134 window.addEventListener('offline', function () { /* wait for an action; do not interrupt */ }); 135})();
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.