UNPKG

451-tools

Version:

Censorship resilient and distributed publishing: informed by the needs of publishers and their audiences, More Mirrors implements a set of offline fallback strategies for censorship resilient websites.

206 lines (171 loc) 13.6 kB
(() => { const template = document.createElement('template'); template.innerHTML = ` <div class="button"> <div class="status status--unknown"> <span class="visually-hidden"></span> <svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M52.137 92.76a8.95 8.95 0 0 1-2.437.36c-.035 0-.069-.003-.104-.003-6.909-.059-13.116-8.343-16.638-20.505 4.853-1.173 10.096-1.81 15.498-1.897.326-1.481.761-2.92 1.298-4.31l-.083-.002c-6.186 0-12.206.718-17.777 2.072-1.129-5.031-1.819-10.575-1.956-16.378h31.368a29.802 29.802 0 0 1 12.359-4.638c-.154-6.133-.868-11.924-2.053-17.181 4.778-1.503 9.139-3.496 12.868-5.935a42.913 42.913 0 0 1 8.394 23.477H83.92a29.905 29.905 0 0 1 13.086 6.389c.125-1.401.2-2.817.2-4.251 0-26.158-21.281-47.44-47.44-47.44l-.062.002-.033-.002c-.035 0-.07.005-.105.005-26.066.109-47.24 21.344-47.24 47.436S23.5 97.286 49.567 97.394c.035 0 .07.005.105.005l.033-.002.062.002c1.884 0 3.738-.123 5.565-.337a30.125 30.125 0 0 1-3.195-4.302zM29.938 47.82c.137-5.802.828-11.346 1.956-16.377 5.571 1.354 11.592 2.072 17.777 2.072 6.189 0 12.208-.718 17.777-2.072 1.129 5.031 1.819 10.574 1.956 16.377H29.938zm51.813-26.813c-3.266 2.083-7.047 3.811-11.198 5.135-2.152-7.456-5.298-13.584-9.11-17.728a43.232 43.232 0 0 1 20.308 12.593zM49.597 6.8c.035 0 .069-.003.104-.003 6.928.023 13.155 8.32 16.685 20.511-5.216 1.261-10.876 1.929-16.714 1.929-5.835 0-11.495-.67-16.713-1.932C36.481 15.143 42.687 6.86 49.597 6.8zm-11.76 1.686c-3.784 4.143-6.906 10.242-9.046 17.656-4.099-1.307-7.838-3.01-11.076-5.058A43.233 43.233 0 0 1 37.837 8.486zM14.992 24.428c3.7 2.4 8.016 4.365 12.739 5.85-1.209 5.362-1.935 11.274-2.07 17.542H6.657a42.915 42.915 0 0 1 8.335-23.392zm0 51.062a42.915 42.915 0 0 1-8.335-23.393h19.004c.135 6.268.861 12.181 2.07 17.542-4.723 1.486-9.039 3.451-12.739 5.851zm2.723 3.343c3.238-2.048 6.977-3.75 11.076-5.057 2.14 7.414 5.263 13.513 9.046 17.656a43.235 43.235 0 0 1-20.122-12.599z"/><path d="M77.738 56.003c-11.686 0-21.16 9.474-21.16 21.16s9.474 21.16 21.16 21.16 21.16-9.474 21.16-21.16c0-11.687-9.474-21.16-21.16-21.16zM63.573 72.461a2.591 2.591 0 0 1 3.637-.38l4.796 3.891 10.419-13.605a2.585 2.585 0 1 1 4.105 3.143L74.493 81.226a2.585 2.585 0 0 1-3.68.437l-6.859-5.564a2.586 2.586 0 0 1-.381-3.638zm25.428 5.827L76.965 94.004a2.585 2.585 0 0 1-3.68.437l-6.859-5.564a2.586 2.586 0 1 1 3.257-4.017l4.796 3.891 10.419-13.605a2.584 2.584 0 1 1 4.103 3.142z"/></svg> </div> <div class="status status--up"> <span class="visually-hidden"></span> <svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M52.137 92.76a8.95 8.95 0 0 1-2.437.36c-.035 0-.069-.003-.104-.003-6.909-.059-13.116-8.343-16.638-20.505 4.853-1.173 10.096-1.81 15.498-1.897.326-1.481.761-2.92 1.298-4.31l-.083-.002c-6.186 0-12.206.718-17.777 2.072-1.129-5.031-1.819-10.575-1.956-16.378h31.368a29.802 29.802 0 0 1 12.359-4.638c-.154-6.133-.868-11.924-2.053-17.181 4.778-1.503 9.139-3.496 12.868-5.935a42.913 42.913 0 0 1 8.394 23.477H83.92a29.905 29.905 0 0 1 13.086 6.389c.125-1.401.2-2.817.2-4.251 0-26.158-21.281-47.44-47.44-47.44l-.062.002-.033-.002c-.035 0-.07.005-.105.005-26.066.109-47.24 21.344-47.24 47.436S23.5 97.286 49.567 97.394c.035 0 .07.005.105.005l.033-.002.062.002c1.884 0 3.738-.123 5.565-.337a30.125 30.125 0 0 1-3.195-4.302zM29.938 47.82c.137-5.802.828-11.346 1.956-16.377 5.571 1.354 11.592 2.072 17.777 2.072 6.189 0 12.208-.718 17.777-2.072 1.129 5.031 1.819 10.574 1.956 16.377H29.938zm51.813-26.813c-3.266 2.083-7.047 3.811-11.198 5.135-2.152-7.456-5.298-13.584-9.11-17.728a43.232 43.232 0 0 1 20.308 12.593zM49.597 6.8c.035 0 .069-.003.104-.003 6.928.023 13.155 8.32 16.685 20.511-5.216 1.261-10.876 1.929-16.714 1.929-5.835 0-11.495-.67-16.713-1.932C36.481 15.143 42.687 6.86 49.597 6.8zm-11.76 1.686c-3.784 4.143-6.906 10.242-9.046 17.656-4.099-1.307-7.838-3.01-11.076-5.058A43.233 43.233 0 0 1 37.837 8.486zM14.992 24.428c3.7 2.4 8.016 4.365 12.739 5.85-1.209 5.362-1.935 11.274-2.07 17.542H6.657a42.915 42.915 0 0 1 8.335-23.392zm0 51.062a42.915 42.915 0 0 1-8.335-23.393h19.004c.135 6.268.861 12.181 2.07 17.542-4.723 1.486-9.039 3.451-12.739 5.851zm2.723 3.343c3.238-2.048 6.977-3.75 11.076-5.057 2.14 7.414 5.263 13.513 9.046 17.656a43.235 43.235 0 0 1-20.122-12.599z"/><path d="M77.738 56.003c-11.686 0-21.16 9.474-21.16 21.16s9.474 21.16 21.16 21.16 21.16-9.474 21.16-21.16c0-11.687-9.474-21.16-21.16-21.16zM63.573 72.461a2.591 2.591 0 0 1 3.637-.38l4.796 3.891 10.419-13.605a2.585 2.585 0 1 1 4.105 3.143L74.493 81.226a2.585 2.585 0 0 1-3.68.437l-6.859-5.564a2.586 2.586 0 0 1-.381-3.638zm25.428 5.827L76.965 94.004a2.585 2.585 0 0 1-3.68.437l-6.859-5.564a2.586 2.586 0 1 1 3.257-4.017l4.796 3.891 10.419-13.605a2.584 2.584 0 1 1 4.103 3.142z"/></svg> </div> <div class="status status--low"> <span class="visually-hidden"></span> <svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M52.137 92.76a8.95 8.95 0 0 1-2.437.36c-.035 0-.069-.003-.104-.003-6.909-.059-13.116-8.343-16.638-20.505 4.853-1.173 10.096-1.81 15.498-1.897.326-1.481.761-2.92 1.298-4.31l-.083-.002c-6.186 0-12.206.718-17.777 2.072-1.129-5.031-1.819-10.575-1.956-16.378h31.368a29.802 29.802 0 0 1 12.359-4.638c-.154-6.133-.868-11.924-2.053-17.181 4.778-1.503 9.139-3.496 12.868-5.935a42.913 42.913 0 0 1 8.394 23.477H83.92a29.905 29.905 0 0 1 13.086 6.389c.125-1.401.2-2.817.2-4.251 0-26.158-21.281-47.44-47.44-47.44l-.062.002-.033-.002c-.035 0-.07.005-.105.005-26.066.109-47.24 21.344-47.24 47.436S23.5 97.286 49.567 97.394c.035 0 .07.005.105.005l.033-.002.062.002c1.884 0 3.738-.123 5.565-.337a30.125 30.125 0 0 1-3.195-4.302zM29.938 47.82c.137-5.802.828-11.346 1.956-16.377 5.571 1.354 11.592 2.072 17.777 2.072 6.189 0 12.208-.718 17.777-2.072 1.129 5.031 1.819 10.574 1.956 16.377H29.938zm51.813-26.813c-3.266 2.083-7.047 3.811-11.198 5.135-2.152-7.456-5.298-13.584-9.11-17.728a43.232 43.232 0 0 1 20.308 12.593zM49.597 6.8c.035 0 .069-.003.104-.003 6.928.023 13.155 8.32 16.685 20.511-5.216 1.261-10.876 1.929-16.714 1.929-5.835 0-11.495-.67-16.713-1.932C36.481 15.143 42.687 6.86 49.597 6.8zm-11.76 1.686c-3.784 4.143-6.906 10.242-9.046 17.656-4.099-1.307-7.838-3.01-11.076-5.058A43.233 43.233 0 0 1 37.837 8.486zM14.992 24.428c3.7 2.4 8.016 4.365 12.739 5.85-1.209 5.362-1.935 11.274-2.07 17.542H6.657a42.915 42.915 0 0 1 8.335-23.392zm0 51.062a42.915 42.915 0 0 1-8.335-23.393h19.004c.135 6.268.861 12.181 2.07 17.542-4.723 1.486-9.039 3.451-12.739 5.851zm2.723 3.343c3.238-2.048 6.977-3.75 11.076-5.057 2.14 7.414 5.263 13.513 9.046 17.656a43.235 43.235 0 0 1-20.122-12.599z"/><path d="M77.738 56.003c-11.686 0-21.16 9.474-21.16 21.16s9.474 21.16 21.16 21.16 21.16-9.474 21.16-21.16c0-11.687-9.474-21.16-21.16-21.16zm8.644 26.452a2.37 2.37 0 1 1-3.352 3.352l-5.292-5.292-5.292 5.292c-.463.463-1.069.694-1.676.694s-1.213-.231-1.676-.694a2.37 2.37 0 0 1 0-3.352l5.292-5.292-5.292-5.292a2.37 2.37 0 1 1 3.352-3.352l5.292 5.292 5.292-5.292a2.37 2.37 0 1 1 3.352 3.352l-5.292 5.292 5.292 5.292z"/></svg> </div> <div class="status status--down"> <span class="visually-hidden"></span> <svg class="icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path d="M52.137 92.76a8.95 8.95 0 0 1-2.437.36c-.035 0-.069-.003-.104-.003-6.909-.059-13.116-8.343-16.638-20.505 4.853-1.173 10.096-1.81 15.498-1.897.326-1.481.761-2.92 1.298-4.31l-.083-.002c-6.186 0-12.206.718-17.777 2.072-1.129-5.031-1.819-10.575-1.956-16.378h31.368a29.802 29.802 0 0 1 12.359-4.638c-.154-6.133-.868-11.924-2.053-17.181 4.778-1.503 9.139-3.496 12.868-5.935a42.913 42.913 0 0 1 8.394 23.477H83.92a29.905 29.905 0 0 1 13.086 6.389c.125-1.401.2-2.817.2-4.251 0-26.158-21.281-47.44-47.44-47.44l-.062.002-.033-.002c-.035 0-.07.005-.105.005-26.066.109-47.24 21.344-47.24 47.436S23.5 97.286 49.567 97.394c.035 0 .07.005.105.005l.033-.002.062.002c1.884 0 3.738-.123 5.565-.337a30.125 30.125 0 0 1-3.195-4.302zM29.938 47.82c.137-5.802.828-11.346 1.956-16.377 5.571 1.354 11.592 2.072 17.777 2.072 6.189 0 12.208-.718 17.777-2.072 1.129 5.031 1.819 10.574 1.956 16.377H29.938zm51.813-26.813c-3.266 2.083-7.047 3.811-11.198 5.135-2.152-7.456-5.298-13.584-9.11-17.728a43.232 43.232 0 0 1 20.308 12.593zM49.597 6.8c.035 0 .069-.003.104-.003 6.928.023 13.155 8.32 16.685 20.511-5.216 1.261-10.876 1.929-16.714 1.929-5.835 0-11.495-.67-16.713-1.932C36.481 15.143 42.687 6.86 49.597 6.8zm-11.76 1.686c-3.784 4.143-6.906 10.242-9.046 17.656-4.099-1.307-7.838-3.01-11.076-5.058A43.233 43.233 0 0 1 37.837 8.486zM14.992 24.428c3.7 2.4 8.016 4.365 12.739 5.85-1.209 5.362-1.935 11.274-2.07 17.542H6.657a42.915 42.915 0 0 1 8.335-23.392zm0 51.062a42.915 42.915 0 0 1-8.335-23.393h19.004c.135 6.268.861 12.181 2.07 17.542-4.723 1.486-9.039 3.451-12.739 5.851zm2.723 3.343c3.238-2.048 6.977-3.75 11.076-5.057 2.14 7.414 5.263 13.513 9.046 17.656a43.235 43.235 0 0 1-20.122-12.599z"/><path d="M77.738 56.003c-11.686 0-21.16 9.474-21.16 21.16s9.474 21.16 21.16 21.16 21.16-9.474 21.16-21.16c0-11.687-9.474-21.16-21.16-21.16zm8.644 26.452a2.37 2.37 0 1 1-3.352 3.352l-5.292-5.292-5.292 5.292c-.463.463-1.069.694-1.676.694s-1.213-.231-1.676-.694a2.37 2.37 0 0 1 0-3.352l5.292-5.292-5.292-5.292a2.37 2.37 0 1 1 3.352-3.352l5.292 5.292 5.292-5.292a2.37 2.37 0 1 1 3.352 3.352l-5.292 5.292 5.292 5.292z"/></svg> </div> </div> <style> *, *::before, *::after { box-sizing: border-box; } .button { appearance: none; border-radius: 0.25rem; border: none; bottom: 1.5rem; fill: black; height: 3rem; left: 1.5rem; padding: 0.5rem; position: fixed; transition: background-color 0.15s ease-in-out, transform 0.15s ease-in-out; width: 3rem; z-index: 1000; } .button.has-link:hover { transform: scale(1.15); } .button.up { background-color: #00E676; } .button.has-link.up:hover { background-color: #00C853; } .button.low { background-color: #F5B82F; } .button.has-link.low:hover { background-color: #E0A735; } .button.down { background-color: #FF1744; } .button.has-link.down:hover { background-color: #D50000; } .button a { height: 100%; left: 0; padding: 0.5rem; position: absolute; top: 0; width: 100%; } .status { display: none; } .unknown .status--unknown { display: block; } .up .status--up { display: block; } .low .status--low { display: block; } .down .status--down { display: block; } .icon { height: auto; width: 100%; } .visually-hidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } </style> `; class TrafficLight extends HTMLElement { constructor () { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.appendChild(template.content.cloneNode(true)); this.button = shadowRoot.querySelector('.button'); navigator.serviceWorker.addEventListener('message', (event) => { const payload = JSON.parse(event.data); if (payload.type === 'mirror-status-changed') { this.setNetworkStatus(); } }); } connectedCallback () { this.setNetworkStatus(); this.button.querySelector('.status--unknown span').textContent = this.unknownText; this.button.querySelector('.status--up span').textContent = this.upText; this.button.querySelector('.status--low span').textContent = this.lowText; this.button.querySelector('.status--down span').textContent = this.downText; if (this.href) { const a = document.createElement('a'); a.href = this.href; a.innerHTML = this.button.innerHTML; if (this.target) a.target = this.target; if (this.rel) a.rel = this.rel; this.button.classList.add('has-link'); this.button.innerHTML = a.outerHTML; } } async setNetworkStatus () { const status = await fetch('/451-tools/mirror-status/') .then(response => { if (!response.ok) { throw new Error('Unable to call mirror status endpoint'); } return response.json(); }) .then(data => data.status) // unknown, up. down or low .catch(() => 'unknown'); this.button.classList.remove('unknown', 'up', 'down', 'low'); this.button.classList.add(status); this.button.setAttribute( 'part', `button ${status}` ); } get unknownText () { return this.getAttribute('unknown-text') || 'Unknown'; } get upText () { return this.getAttribute('up-text') || 'Online'; } get lowText () { return this.getAttribute('low-text') || 'Low'; } get downText () { return this.getAttribute('down-text') || 'Offline'; } get href () { return this.getAttribute('href'); } get target () { return this.getAttribute('target'); } get rel () { return this.getAttribute('rel'); } } customElements.define('traffic-light', TrafficLight); })();