/** * Author: Vera Konigin * Site: https://groundedwren.neocities.org * Contact: vera@groundedwren.com * * File Description: A web component to site SVG icons easily */ /** * By default, any JavaScript code written is defined in the global namespace, which means it's accessible directly under the "window" element. * If you have a lot of scripts, this can lead to clutter and naming collisions (what if two different scripts use a variable called "i"? They can inadvertently mess each other up). * To get around this, we define the registerNamespace function in the global namespace, which just confines all the code in the function passed to it to a property under window. * That property is represented as the "path" parameter. It is passed to the function for ease of access. */ function registerNamespace(path, nsFunc) { var ancestors = path.split("."); var ns = window; for(var i = 0; i < ancestors.length; i++) { ns[ancestors[i]] = ns[ancestors[i]] || {}; ns = ns[ancestors[i]]; } nsFunc(ns); } registerNamespace("GW.Controls.SVGLib", function(ns) { const XML_NAMESPACE = "http://www.w3.org/2000/svg"; /** * https://www.w3.org/TR/SVG/eltindex.html */ ns.ElementTypes = { svg: "svg", //viewBox, preserveAspectRatio, zoomAndPan, transform - https://www.w3.org/TR/SVG/struct.html#SVGElement circle: "circle", //cx, cy, r - https://www.w3.org/TR/SVG/shapes.html#CircleElement linearGradient: "linearGradient", //x1, y1, x2, y2, gradientUnits, gradientTransform, spreadMethod, href - https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement stop: "stop", //offset, stop-color https://www.w3.org/TR/SVG/pservers.html#StopElement defs: "defs", //https://www.w3.org/TR/SVG/struct.html#DefsElement rect: "rect", //x, y, width, height, rx, ry - https://www.w3.org/TR/SVG/shapes.html#RectElement text: "text", //x, y, dominant-baseline, text-anchor, fill - https://www.w3.org/TR/SVG/text.html#TextElement a: "a", //href, target - https://developer.mozilla.org/en-US/docs/Web/SVG/Element/a path: "path", //d, pathLength - https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path title: "title", // - https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title desc: "desc", // - https://developer.mozilla.org/en-US/docs/Web/SVG/Element/desc foreignObject: "foreignObject", // - https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject }; /** * Shortcut to create an SVG element and append it to a parent * @param parent the parent element * ... see ns.createElement */ function createChildElement(parent, elementType, attributes, innerHTML) { var childEl = createElement(elementType, attributes, innerHTML); parent.appendChild(childEl); return childEl; } ns.createChildElement = createChildElement; /** * Creates an SVG element to spec * @param elementType type of SVG element (see ns.ElementTypes) * @param attributes object of attributes and values * @param innerHTML inner HTML */ function createElement(elementType, attributes, innerHTML) { var el = document.createElementNS(XML_NAMESPACE, elementType); Object.keys(attributes || {}).forEach((attr) => el.setAttributeNS(null, attr, attributes[attr])); el.innerHTML = innerHTML || null; return el; } ns.createElement = createElement; //#region Icons const ICON_CITATION = ""; const ICON_CLASS = "icon"; /** * Icon SVG path definitions */ ns.Icons = { "circle-info": { title: "info", viewBox: "0 0 512 512", d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z" }, "play": { title: "play", viewBox: "0 0 384 512", d: "M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z" }, "backward-step": { title: "backward step", viewBox: "0 0 320 512", d: "M267.5 440.6c9.5 7.9 22.8 9.7 34.1 4.4s18.4-16.6 18.4-29V96c0-12.4-7.2-23.7-18.4-29s-24.5-3.6-34.1 4.4l-192 160L64 241V96c0-17.7-14.3-32-32-32S0 78.3 0 96V416c0 17.7 14.3 32 32 32s32-14.3 32-32V271l11.5 9.6 192 160z" }, "forward-step": { title: "forward step", viewBox: "0 0 320 512", d: "M52.5 440.6c-9.5 7.9-22.8 9.7-34.1 4.4S0 428.4 0 416V96C0 83.6 7.2 72.3 18.4 67s24.5-3.6 34.1 4.4l192 160L256 241V96c0-17.7 14.3-32 32-32s32 14.3 32 32V416c0 17.7-14.3 32-32 32s-32-14.3-32-32V271l-11.5 9.6-192 160z" }, "pause": { title: "pause", viewBox: "0 0 320 512", d: "M48 64C21.5 64 0 85.5 0 112V400c0 26.5 21.5 48 48 48H80c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48H48zm192 0c-26.5 0-48 21.5-48 48V400c0 26.5 21.5 48 48 48h32c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48H240z" }, "triangle-exclamation": { title: "warning", viewBox: "0 0 512 512", d: "M256 32c14.2 0 27.3 7.5 34.5 19.8l216 368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480H40c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7 39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24V296c0 13.3 10.7 24 24 24s24-10.7 24-24V184c0-13.3-10.7-24-24-24zm32 224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z" }, "laptop-code": { title: "coding", viewBox: "0 0 640 512", d: "M64 96c0-35.3 28.7-64 64-64H512c35.3 0 64 28.7 64 64V352H512V96H128V352H64V96zM0 403.2C0 392.6 8.6 384 19.2 384H620.8c10.6 0 19.2 8.6 19.2 19.2c0 42.4-34.4 76.8-76.8 76.8H76.8C34.4 480 0 445.6 0 403.2zM281 209l-31 31 31 31c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-48-48c-9.4-9.4-9.4-24.6 0-33.9l48-48c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9zM393 175l48 48c9.4 9.4 9.4 24.6 0 33.9l-48 48c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l31-31-31-31c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0z" }, "guitar": { title: "guitar", viewBox: "0 0 512 512", d: "M465 7c-9.4-9.4-24.6-9.4-33.9 0L383 55c-2.4 2.4-4.3 5.3-5.5 8.5l-15.4 41-77.5 77.6c-45.1-29.4-99.3-30.2-131 1.6c-11 11-18 24.6-21.4 39.6c-3.7 16.6-19.1 30.7-36.1 31.6c-25.6 1.3-49.3 10.7-67.3 28.6C-16 328.4-7.6 409.4 47.5 464.5s136.1 63.5 180.9 18.7c17.9-17.9 27.4-41.7 28.6-67.3c.9-17 15-32.3 31.6-36.1c15-3.4 28.6-10.5 39.6-21.4c31.8-31.8 31-85.9 1.6-131l77.6-77.6 41-15.4c3.2-1.2 6.1-3.1 8.5-5.5l48-48c9.4-9.4 9.4-24.6 0-33.9L465 7zM208 256a48 48 0 1 1 0 96 48 48 0 1 1 0-96z" }, "pen-fancy": { title: "pen", viewBox: "0 0 512 512", d: "M373.5 27.1C388.5 9.9 410.2 0 433 0c43.6 0 79 35.4 79 79c0 22.8-9.9 44.6-27.1 59.6L277.7 319l-10.3-10.3-64-64L193 234.3 373.5 27.1zM170.3 256.9l10.4 10.4 64 64 10.4 10.4-19.2 83.4c-3.9 17.1-16.9 30.7-33.8 35.4L24.4 510.3l95.4-95.4c2.6 .7 5.4 1.1 8.3 1.1c17.7 0 32-14.3 32-32s-14.3-32-32-32s-32 14.3-32 32c0 2.9 .4 5.6 1.1 8.3L1.7 487.6 51.5 310c4.7-16.9 18.3-29.9 35.4-33.8l83.4-19.2z" }, "glasses": { title: "glasses", viewBox: "0 0 576 512", d: "M118.6 80c-11.5 0-21.4 7.9-24 19.1L57 260.3c20.5-6.2 48.3-12.3 78.7-12.3c32.3 0 61.8 6.9 82.8 13.5c10.6 3.3 19.3 6.7 25.4 9.2c3.1 1.3 5.5 2.4 7.3 3.2c.9 .4 1.6 .7 2.1 1l.6 .3 .2 .1 .1 0 0 0 0 0s0 0-6.3 12.7h0l6.3-12.7c5.8 2.9 10.4 7.3 13.5 12.7h40.6c3.1-5.3 7.7-9.8 13.5-12.7l6.3 12.7h0c-6.3-12.7-6.3-12.7-6.3-12.7l0 0 0 0 .1 0 .2-.1 .6-.3c.5-.2 1.2-.6 2.1-1c1.8-.8 4.2-1.9 7.3-3.2c6.1-2.6 14.8-5.9 25.4-9.2c21-6.6 50.4-13.5 82.8-13.5c30.4 0 58.2 6.1 78.7 12.3L481.4 99.1c-2.6-11.2-12.6-19.1-24-19.1c-3.1 0-6.2 .6-9.2 1.8L416.9 94.3c-12.3 4.9-26.3-1.1-31.2-13.4s1.1-26.3 13.4-31.2l31.3-12.5c8.6-3.4 17.7-5.2 27-5.2c33.8 0 63.1 23.3 70.8 56.2l43.9 188c1.7 7.3 2.9 14.7 3.5 22.1c.3 1.9 .5 3.8 .5 5.7v6.7V352v16c0 61.9-50.1 112-112 112H419.7c-59.4 0-108.5-46.4-111.8-105.8L306.6 352H269.4l-1.2 22.2C264.9 433.6 215.8 480 156.3 480H112C50.1 480 0 429.9 0 368V352 310.7 304c0-1.9 .2-3.8 .5-5.7c.6-7.4 1.8-14.8 3.5-22.1l43.9-188C55.5 55.3 84.8 32 118.6 32c9.2 0 18.4 1.8 27 5.2l31.3 12.5c12.3 4.9 18.3 18.9 13.4 31.2s-18.9 18.3-31.2 13.4L127.8 81.8c-2.9-1.2-6-1.8-9.2-1.8zM64 325.4V368c0 26.5 21.5 48 48 48h44.3c25.5 0 46.5-19.9 47.9-45.3l2.5-45.6c-2.3-.8-4.9-1.7-7.5-2.5c-17.2-5.4-39.9-10.5-63.6-10.5c-23.7 0-46.2 5.1-63.2 10.5c-3.1 1-5.9 1.9-8.5 2.9zM512 368V325.4c-2.6-.9-5.5-1.9-8.5-2.9c-17-5.4-39.5-10.5-63.2-10.5c-23.7 0-46.4 5.1-63.6 10.5c-2.7 .8-5.2 1.7-7.5 2.5l2.5 45.6c1.4 25.4 22.5 45.3 47.9 45.3H464c26.5 0 48-21.5 48-48z" }, "clock": { title: "glasses", viewBox: "0 0 512 512", d: "M256 0a256 256 0 1 1 0 512A256 256 0 1 1 256 0zM232 120V256c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2V120c0-13.3-10.7-24-24-24s-24 10.7-24 24z" }, "envelope": { title: "envelope", viewBox: "0 0 512 512", d: "M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z" }, "discord": { title: "discord", viewBox: "0 0 640 512", d: "M524.531,69.836a1.5,1.5,0,0,0-.764-.7A485.065,485.065,0,0,0,404.081,32.03a1.816,1.816,0,0,0-1.923.91,337.461,337.461,0,0,0-14.9,30.6,447.848,447.848,0,0,0-134.426,0,309.541,309.541,0,0,0-15.135-30.6,1.89,1.89,0,0,0-1.924-.91A483.689,483.689,0,0,0,116.085,69.137a1.712,1.712,0,0,0-.788.676C39.068,183.651,18.186,294.69,28.43,404.354a2.016,2.016,0,0,0,.765,1.375A487.666,487.666,0,0,0,176.02,479.918a1.9,1.9,0,0,0,2.063-.676A348.2,348.2,0,0,0,208.12,430.4a1.86,1.86,0,0,0-1.019-2.588,321.173,321.173,0,0,1-45.868-21.853,1.885,1.885,0,0,1-.185-3.126c3.082-2.309,6.166-4.711,9.109-7.137a1.819,1.819,0,0,1,1.9-.256c96.229,43.917,200.41,43.917,295.5,0a1.812,1.812,0,0,1,1.924.233c2.944,2.426,6.027,4.851,9.132,7.16a1.884,1.884,0,0,1-.162,3.126,301.407,301.407,0,0,1-45.89,21.83,1.875,1.875,0,0,0-1,2.611,391.055,391.055,0,0,0,30.014,48.815,1.864,1.864,0,0,0,2.063.7A486.048,486.048,0,0,0,610.7,405.729a1.882,1.882,0,0,0,.765-1.352C623.729,277.594,590.933,167.465,524.531,69.836ZM222.491,337.58c-28.972,0-52.844-26.587-52.844-59.239S193.056,219.1,222.491,219.1c29.665,0,53.306,26.82,52.843,59.239C275.334,310.993,251.924,337.58,222.491,337.58Zm195.38,0c-28.971,0-52.843-26.587-52.843-59.239S388.437,219.1,417.871,219.1c29.667,0,53.307,26.82,52.844,59.239C470.715,310.993,447.538,337.58,417.871,337.58Z" }, "plus": { title: "plus", viewBox: "0 0 448 512", d: "M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32V224H48c-17.7 0-32 14.3-32 32s14.3 32 32 32H192V432c0 17.7 14.3 32 32 32s32-14.3 32-32V288H400c17.7 0 32-14.3 32-32s-14.3-32-32-32H256V80z" }, "circle-check": { title: "done", viewBox: "0 0 512 512", d: "M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM369 209L241 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L335 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z" }, "delete-left": { title: "delete", viewBox: "0 0 576 512", d: "M576 128c0-35.3-28.7-64-64-64H205.3c-17 0-33.3 6.7-45.3 18.7L9.4 233.4c-6 6-9.4 14.1-9.4 22.6s3.4 16.6 9.4 22.6L160 429.3c12 12 28.3 18.7 45.3 18.7H512c35.3 0 64-28.7 64-64V128zM271 175c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z" }, "link": { title: "link", viewBox: "0 0 640 512", d: "M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z" }, "xmark": { title: "close", viewBox: "0 0 384 512", d: "M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z" }, "trash": { title: "trash", viewBox: "0 0 448 512", d: "M135.2 17.7L128 32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H320l-7.2-14.3C307.4 6.8 296.3 0 284.2 0H163.8c-12.1 0-23.2 6.8-28.6 17.7zM416 128H32L53.2 467c1.6 25.3 22.6 45 47.9 45H346.9c25.3 0 46.3-19.7 47.9-45L416 128z" }, "thumbtack": { title: "trash", viewBox: "0 0 384 512", d: "M32 32C32 14.3 46.3 0 64 0H320c17.7 0 32 14.3 32 32s-14.3 32-32 32H290.5l11.4 148.2c36.7 19.9 65.7 53.2 79.5 94.7l1 3c3.3 9.8 1.6 20.5-4.4 28.8s-15.7 13.3-26 13.3H32c-10.3 0-19.9-4.9-26-13.3s-7.7-19.1-4.4-28.8l1-3c13.8-41.5 42.8-74.8 79.5-94.7L93.5 64H64C46.3 64 32 49.7 32 32zM160 384h64v96c0 17.7-14.3 32-32 32s-32-14.3-32-32V384z" }, "pen-to-square": { title: "edit", viewBox: "0 0 512 512", d: "M471.6 21.7c-21.9-21.9-57.3-21.9-79.2 0L362.3 51.7l97.9 97.9 30.1-30.1c21.9-21.9 21.9-57.3 0-79.2L471.6 21.7zm-299.2 220c-6.1 6.1-10.8 13.6-13.5 21.9l-29.6 88.8c-2.9 8.6-.6 18.1 5.8 24.6s15.9 8.7 24.6 5.8l88.8-29.6c8.2-2.7 15.7-7.4 21.9-13.5L437.7 172.3 339.7 74.3 172.4 241.7zM96 64C43 64 0 107 0 160V416c0 53 43 96 96 96H352c53 0 96-43 96-96V320c0-17.7-14.3-32-32-32s-32 14.3-32 32v96c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H96z" }, "book": { title: "book", viewBox: "0 0 448 512", d: "M96 0C43 0 0 43 0 96V416c0 53 43 96 96 96H384h32c17.7 0 32-14.3 32-32s-14.3-32-32-32V384c17.7 0 32-14.3 32-32V32c0-17.7-14.3-32-32-32H384 96zm0 384H352v64H96c-17.7 0-32-14.3-32-32s14.3-32 32-32zm32-240c0-8.8 7.2-16 16-16H336c8.8 0 16 7.2 16 16s-7.2 16-16 16H144c-8.8 0-16-7.2-16-16zm16 48H336c8.8 0 16 7.2 16 16s-7.2 16-16 16H144c-8.8 0-16-7.2-16-16s7.2-16 16-16z" }, "gamepad": { title: "game", viewBox: "0 0 640 512", d: "M192 64C86 64 0 150 0 256S86 448 192 448H448c106 0 192-86 192-192s-86-192-192-192H192zM496 168a40 40 0 1 1 0 80 40 40 0 1 1 0-80zM392 304a40 40 0 1 1 80 0 40 40 0 1 1 -80 0zM168 200c0-13.3 10.7-24 24-24s24 10.7 24 24v32h32c13.3 0 24 10.7 24 24s-10.7 24-24 24H216v32c0 13.3-10.7 24-24 24s-24-10.7-24-24V280H136c-13.3 0-24-10.7-24-24s10.7-24 24-24h32V200z" }, "hammer": { title: "game", viewBox: "0 0 576 512", d: "M413.5 237.5c-28.2 4.8-58.2-3.6-80-25.4l-38.1-38.1C280.4 159 272 138.8 272 117.6V105.5L192.3 62c-5.3-2.9-8.6-8.6-8.3-14.7s3.9-11.5 9.5-14l47.2-21C259.1 4.2 279 0 299.2 0h18.1c36.7 0 72 14 98.7 39.1l44.6 42c24.2 22.8 33.2 55.7 26.6 86L503 183l8-8c9.4-9.4 24.6-9.4 33.9 0l24 24c9.4 9.4 9.4 24.6 0 33.9l-88 88c-9.4 9.4-24.6 9.4-33.9 0l-24-24c-9.4-9.4-9.4-24.6 0-33.9l8-8-17.5-17.5zM27.4 377.1L260.9 182.6c3.5 4.9 7.5 9.6 11.8 14l38.1 38.1c6 6 12.4 11.2 19.2 15.7L134.9 484.6c-14.5 17.4-36 27.4-58.6 27.4C34.1 512 0 477.8 0 435.7c0-22.6 10.1-44.1 27.4-58.6z" }, "location-dot": { title: "location", viewBox: "0 0 384 512", d: "M215.7 499.2C267 435 384 279.4 384 192C384 86 298 0 192 0S0 86 0 192c0 87.4 117 243 168.3 307.2c12.3 15.3 35.1 15.3 47.4 0zM192 128a64 64 0 1 1 0 128 64 64 0 1 1 0-128z" }, "box-open": { title: "box", viewBox: "0 0 640 512", d: "M58.9 42.1c3-6.1 9.6-9.6 16.3-8.7L320 64 564.8 33.4c6.7-.8 13.3 2.7 16.3 8.7l41.7 83.4c9 17.9-.6 39.6-19.8 45.1L439.6 217.3c-13.9 4-28.8-1.9-36.2-14.3L320 64 236.6 203c-7.4 12.4-22.3 18.3-36.2 14.3L37.1 170.6c-19.3-5.5-28.8-27.2-19.8-45.1L58.9 42.1zM321.1 128l54.9 91.4c14.9 24.8 44.6 36.6 72.5 28.6L576 211.6v167c0 22-15 41.2-36.4 46.6l-204.1 51c-10.2 2.6-20.9 2.6-31 0l-204.1-51C79 419.7 64 400.5 64 378.5v-167L191.6 248c27.8 8 57.6-3.8 72.5-28.6L318.9 128h2.2z" }, "calendar": { title: "box", viewBox: "0 0 448 512", d: "M128 0c17.7 0 32 14.3 32 32V64H288V32c0-17.7 14.3-32 32-32s32 14.3 32 32V64h48c26.5 0 48 21.5 48 48v48H0V112C0 85.5 21.5 64 48 64H96V32c0-17.7 14.3-32 32-32zM0 192H448V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V192zm64 80v32c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V272c0-8.8-7.2-16-16-16H80c-8.8 0-16 7.2-16 16zm128 0v32c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V272c0-8.8-7.2-16-16-16H208c-8.8 0-16 7.2-16 16zm144-16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V272c0-8.8-7.2-16-16-16H336zM64 400v32c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V400c0-8.8-7.2-16-16-16H80c-8.8 0-16 7.2-16 16zm144-16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V400c0-8.8-7.2-16-16-16H208zm112 16v32c0 8.8 7.2 16 16 16h32c8.8 0 16-7.2 16-16V400c0-8.8-7.2-16-16-16H336c-8.8 0-16 7.2-16 16z" }, "people-group": { title: "people", viewBox: "0 0 640 512", d: "M72 88a56 56 0 1 1 112 0A56 56 0 1 1 72 88zM64 245.7C54 256.9 48 271.8 48 288s6 31.1 16 42.3V245.7zm144.4-49.3C178.7 222.7 160 261.2 160 304c0 34.3 12 65.8 32 90.5V416c0 17.7-14.3 32-32 32H96c-17.7 0-32-14.3-32-32V389.2C26.2 371.2 0 332.7 0 288c0-61.9 50.1-112 112-112h32c24 0 46.2 7.5 64.4 20.3zM448 416V394.5c20-24.7 32-56.2 32-90.5c0-42.8-18.7-81.3-48.4-107.7C449.8 183.5 472 176 496 176h32c61.9 0 112 50.1 112 112c0 44.7-26.2 83.2-64 101.2V416c0 17.7-14.3 32-32 32H480c-17.7 0-32-14.3-32-32zm8-328a56 56 0 1 1 112 0A56 56 0 1 1 456 88zM576 245.7v84.7c10-11.3 16-26.1 16-42.3s-6-31.1-16-42.3zM320 32a64 64 0 1 1 0 128 64 64 0 1 1 0-128zM240 304c0 16.2 6 31 16 42.3V261.7c-10 11.3-16 26.1-16 42.3zm144-42.3v84.7c10-11.3 16-26.1 16-42.3s-6-31.1-16-42.3zM448 304c0 44.7-26.2 83.2-64 101.2V448c0 17.7-14.3 32-32 32H288c-17.7 0-32-14.3-32-32V405.2c-37.8-18-64-56.5-64-101.2c0-61.9 50.1-112 112-112h32c61.9 0 112 50.1 112 112z" }, "comments": { title: "comments", viewBox: "0 0 640 512", d: "M208 352c114.9 0 208-78.8 208-176S322.9 0 208 0S0 78.8 0 176c0 38.6 14.7 74.3 39.6 103.4c-3.5 9.4-8.7 17.7-14.2 24.7c-4.8 6.2-9.7 11-13.3 14.3c-1.8 1.6-3.3 2.9-4.3 3.7c-.5 .4-.9 .7-1.1 .8l-.2 .2 0 0 0 0C1 327.2-1.4 334.4 .8 340.9S9.1 352 16 352c21.8 0 43.8-5.6 62.1-12.5c9.2-3.5 17.8-7.4 25.3-11.4C134.1 343.3 169.8 352 208 352zM448 176c0 112.3-99.1 196.9-216.5 207C255.8 457.4 336.4 512 432 512c38.2 0 73.9-8.7 104.7-23.9c7.5 4 16 7.9 25.2 11.4c18.3 6.9 40.3 12.5 62.1 12.5c6.9 0 13.1-4.5 15.2-11.1c2.1-6.6-.2-13.8-5.8-17.9l0 0 0 0-.2-.2c-.2-.2-.6-.4-1.1-.8c-1-.8-2.5-2-4.3-3.7c-3.6-3.3-8.5-8.1-13.3-14.3c-5.5-7-10.7-15.4-14.2-24.7c24.9-29 39.6-64.7 39.6-103.4c0-92.8-84.9-168.9-192.6-175.5c.4 5.1 .6 10.3 .6 15.5z" }, "clipboard-check": { title: "clipboard", viewBox: "0 0 384 512", d: "M192 0c-41.8 0-77.4 26.7-90.5 64H64C28.7 64 0 92.7 0 128V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V128c0-35.3-28.7-64-64-64H282.5C269.4 26.7 233.8 0 192 0zm0 64a32 32 0 1 1 0 64 32 32 0 1 1 0-64zM305 273L177 401c-9.4 9.4-24.6 9.4-33.9 0L79 337c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L271 239c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z" }, "user": { title: "clipboard", viewBox: "0 0 448 512", d: "M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z" }, "door-open": { title: "open door", viewBox: "0 0 576 512", d: "M320 32c0-9.9-4.5-19.2-12.3-25.2S289.8-1.4 280.2 1l-179.9 45C79 51.3 64 70.5 64 92.5V448H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H96 288h32V480 32zM256 256c0 17.7-10.7 32-24 32s-24-14.3-24-32s10.7-32 24-32s24 14.3 24 32zm96-128h96V480c0 17.7 14.3 32 32 32h64c17.7 0 32-14.3 32-32s-14.3-32-32-32H512V128c0-35.3-28.7-64-64-64H352v64z" }, "scroll": { title: "scroll", viewBox: "0 0 576 512", d: "M0 80v48c0 17.7 14.3 32 32 32H48 96V80c0-26.5-21.5-48-48-48S0 53.5 0 80zM112 32c10 13.4 16 30 16 48V384c0 35.3 28.7 64 64 64s64-28.7 64-64v-5.3c0-32.4 26.3-58.7 58.7-58.7H480V128c0-53-43-96-96-96H112zM464 480c61.9 0 112-50.1 112-112c0-8.8-7.2-16-16-16H314.7c-14.7 0-26.7 11.9-26.7 26.7V384c0 53-43 96-96 96H368h96z" }, "star": { title: "star", viewBox: "0 0 576 512", d: "M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z" }, "boxes-stacked": { title: "stacked boxes", viewBox: "0 0 576 512", d: "M248 0H208c-26.5 0-48 21.5-48 48V160c0 35.3 28.7 64 64 64H352c35.3 0 64-28.7 64-64V48c0-26.5-21.5-48-48-48H328V80c0 8.8-7.2 16-16 16H264c-8.8 0-16-7.2-16-16V0zM64 256c-35.3 0-64 28.7-64 64V448c0 35.3 28.7 64 64 64H224c35.3 0 64-28.7 64-64V320c0-35.3-28.7-64-64-64H184v80c0 8.8-7.2 16-16 16H120c-8.8 0-16-7.2-16-16V256H64zM352 512H512c35.3 0 64-28.7 64-64V320c0-35.3-28.7-64-64-64H472v80c0 8.8-7.2 16-16 16H408c-8.8 0-16-7.2-16-16V256H352c-15 0-28.8 5.1-39.7 13.8c4.9 10.4 7.7 22 7.7 34.2V464c0 12.2-2.8 23.8-7.7 34.2C323.2 506.9 337 512 352 512z" }, "person-running": { title: "person running", viewBox: "0 0 448 512", d: "M320 48a48 48 0 1 0 -96 0 48 48 0 1 0 96 0zM125.7 175.5c9.9-9.9 23.4-15.5 37.5-15.5c1.9 0 3.8 .1 5.6 .3L137.6 254c-9.3 28 1.7 58.8 26.8 74.5l86.2 53.9-25.4 88.8c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l28.7-100.4c5.9-20.6-2.6-42.6-20.7-53.9L238 299l30.9-82.4 5.1 12.3C289 264.7 323.9 288 362.7 288H384c17.7 0 32-14.3 32-32s-14.3-32-32-32H362.7c-12.9 0-24.6-7.8-29.5-19.7l-6.3-15c-14.6-35.1-44.1-61.9-80.5-73.1l-48.7-15c-11.1-3.4-22.7-5.2-34.4-5.2c-31 0-60.8 12.3-82.7 34.3L57.4 153.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l23.1-23.1zM91.2 352H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h69.6c19 0 36.2-11.2 43.9-28.5L157 361.6l-9.5-6c-17.5-10.9-30.5-26.8-37.9-44.9L91.2 352z" }, "handshake": { title: "handshake", viewBox: "0 0 640 512", d: "M323.4 85.2l-96.8 78.4c-16.1 13-19.2 36.4-7 53.1c12.9 17.8 38 21.3 55.3 7.8l99.3-77.2c7-5.4 17-4.2 22.5 2.8s4.2 17-2.8 22.5l-20.9 16.2L550.2 352H592c26.5 0 48-21.5 48-48V176c0-26.5-21.5-48-48-48H516h-4-.7l-3.9-2.5L434.8 79c-15.3-9.8-33.2-15-51.4-15c-21.8 0-43 7.5-60 21.2zm22.8 124.4l-51.7 40.2C263 274.4 217.3 268 193.7 235.6c-22.2-30.5-16.6-73.1 12.7-96.8l83.2-67.3c-11.6-4.9-24.1-7.4-36.8-7.4C234 64 215.7 69.6 200 80l-72 48H48c-26.5 0-48 21.5-48 48V304c0 26.5 21.5 48 48 48H156.2l91.4 83.4c19.6 17.9 49.9 16.5 67.8-3.1c5.5-6.1 9.2-13.2 11.1-20.6l17 15.6c19.5 17.9 49.9 16.6 67.8-2.9c4.5-4.9 7.8-10.6 9.9-16.5c19.4 13 45.8 10.3 62.1-7.5c17.9-19.5 16.6-49.9-2.9-67.8l-134.2-123z" }, "reply": { title: "reply", viewBox: "0 0 512 512", d: "M205 34.8c11.5 5.1 19 16.6 19 29.2v64H336c97.2 0 176 78.8 176 176c0 113.3-81.5 163.9-100.2 174.1c-2.5 1.4-5.3 1.9-8.1 1.9c-10.9 0-19.7-8.9-19.7-19.7c0-7.5 4.3-14.4 9.8-19.5c9.4-8.8 22.2-26.4 22.2-56.7c0-53-43-96-96-96H224v64c0 12.6-7.4 24.1-19 29.2s-25 3-34.4-5.4l-160-144C3.9 225.7 0 217.1 0 208s3.9-17.7 10.6-23.8l160-144c9.4-8.5 22.9-10.6 34.4-5.4z" }, "d20": { title: "d20", viewBox: "0 0 512 512", d: "M48.7 125.8l53.2 31.9c7.8 4.7 17.8 2 22.2-5.9L201.6 12.1c3-5.4-.9-12.1-7.1-12.1c-1.6 0-3.2 .5-4.6 1.4L47.9 98.8c-9.6 6.6-9.2 20.9 .8 26.9zM16 171.7V295.3c0 8 10.4 11 14.7 4.4l60-92c5-7.6 2.6-17.8-5.2-22.5L40.2 158C29.6 151.6 16 159.3 16 171.7zM310.4 12.1l77.6 139.6c4.4 7.9 14.5 10.6 22.2 5.9l53.2-31.9c10-6 10.4-20.3 .8-26.9L322.1 1.4c-1.4-.9-3-1.4-4.6-1.4c-6.2 0-10.1 6.7-7.1 12.1zM496 171.7c0-12.4-13.6-20.1-24.2-13.7l-45.3 27.2c-7.8 4.7-10.1 14.9-5.2 22.5l60 92c4.3 6.7 14.7 3.6 14.7-4.4V171.7zm-49.3 246L286.1 436.6c-8.1 .9-14.1 7.8-14.1 15.9v52.8c0 3.7 3 6.8 6.8 6.8c.8 0 1.6-.1 2.4-.4l172.7-64c6.1-2.2 10.1-8 10.1-14.5c0-9.3-8.1-16.5-17.3-15.4zM233.2 512c3.7 0 6.8-3 6.8-6.8V452.6c0-8.1-6.1-14.9-14.1-15.9l-160.6-19c-9.2-1.1-17.3 6.1-17.3 15.4c0 6.5 4 12.3 10.1 14.5l172.7 64c.8 .3 1.6 .4 2.4 .4zM41.7 382.9l170.9 20.2c7.8 .9 13.4-7.5 9.5-14.3l-85.7-150c-5.9-10.4-20.7-10.8-27.3-.8L30.2 358.2c-6.5 9.9-.3 23.3 11.5 24.7zm439.6-24.8L402.9 238.1c-6.5-10-21.4-9.6-27.3 .8L290.2 388.5c-3.9 6.8 1.6 15.2 9.5 14.3l170.1-20c11.8-1.4 18-14.7 11.5-24.6zm-216.9 11l78.4-137.2c6.1-10.7-1.6-23.9-13.9-23.9H183.1c-12.3 0-20 13.3-13.9 23.9l78.4 137.2c3.7 6.4 13 6.4 16.7 0zM174.4 176H337.6c12.2 0 19.9-13.1 14-23.8l-80-144c-2.8-5.1-8.2-8.2-14-8.2h-3.2c-5.8 0-11.2 3.2-14 8.2l-80 144c-5.9 10.7 1.8 23.8 14 23.8z" }, "screwdriver-wrench": { title: "settings", viewBox: "0 0 512 512", d: "M78.6 5C69.1-2.4 55.6-1.5 47 7L7 47c-8.5 8.5-9.4 22-2.1 31.6l80 104c4.5 5.9 11.6 9.4 19 9.4h54.1l109 109c-14.7 29-10 65.4 14.3 89.6l112 112c12.5 12.5 32.8 12.5 45.3 0l64-64c12.5-12.5 12.5-32.8 0-45.3l-112-112c-24.2-24.2-60.6-29-89.6-14.3l-109-109V104c0-7.5-3.5-14.5-9.4-19L78.6 5zM19.9 396.1C7.2 408.8 0 426.1 0 444.1C0 481.6 30.4 512 67.9 512c18 0 35.3-7.2 48-19.9L233.7 374.3c-7.8-20.9-9-43.6-3.6-65.1l-61.7-61.7L19.9 396.1zM512 144c0-10.5-1.1-20.7-3.2-30.5c-2.4-11.2-16.1-14.1-24.2-6l-63.9 63.9c-3 3-7.1 4.7-11.3 4.7H352c-8.8 0-16-7.2-16-16V102.6c0-4.2 1.7-8.3 4.7-11.3l63.9-63.9c8.1-8.1 5.2-21.8-6-24.2C388.7 1.1 378.5 0 368 0C288.5 0 224 64.5 224 144l0 .8 85.3 85.3c36-9.1 75.8 .5 104 28.7L429 274.5c49-23 83-72.8 83-130.5zM56 432a24 24 0 1 1 48 0 24 24 0 1 1 -48 0z" }, "dumbbell": { title: "dumbbell", viewBox: "0 0 640 512", d: "M96 64c0-17.7 14.3-32 32-32h32c17.7 0 32 14.3 32 32V224v64V448c0 17.7-14.3 32-32 32H128c-17.7 0-32-14.3-32-32V384H64c-17.7 0-32-14.3-32-32V288c-17.7 0-32-14.3-32-32s14.3-32 32-32V160c0-17.7 14.3-32 32-32H96V64zm448 0v64h32c17.7 0 32 14.3 32 32v64c17.7 0 32 14.3 32 32s-14.3 32-32 32v64c0 17.7-14.3 32-32 32H544v64c0 17.7-14.3 32-32 32H480c-17.7 0-32-14.3-32-32V288 224 64c0-17.7 14.3-32 32-32h32c17.7 0 32 14.3 32 32zM416 224v64H224V224H416z" }, "chevron-down": { title: "chevron down", viewBox: "0 0 512 512", d: "M233.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L256 338.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" }, "chevron-up": { title: "chevron up", viewBox: "0 0 512 512", d: "M233.4 105.4c12.5-12.5 32.8-12.5 45.3 0l192 192c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L256 173.3 86.6 342.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l192-192z" }, "chevron-left": { title: "chevron left", viewBox: "0 0 320 512", d: "M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z" }, "chevron-right": { title: "chevron right", viewBox: "0 0 320 512", d: "M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z" }, }; ns.createIcon = function createIcon(iconDef, title, desc, classes, style) { var iconEl = createElement( ns.ElementTypes.svg, { "viewBox": iconDef.viewBox, "class": `${ICON_CLASS} ${classes}`, "role": "img", "style": style || "" }, ICON_CITATION ); iconEl.insertAdjacentHTML("afterbegin", `` ); createChildElement( iconEl, ns.ElementTypes.title, {}, title || iconDef.title ); if (desc) { createChildElement( iconEl, ns.ElementTypes.desc, {}, desc ); } createChildElement( iconEl, ns.ElementTypes.path, { "d": iconDef.d } ); return iconEl; }; //#endregion }); registerNamespace("GW.Controls", function(ns) { ns.IconEl = class IconEl extends HTMLElement { //#region staticProperties static observedAttributes = []; static instanceCount = 0; static instanceMap = {}; //#endregion //#region instance properties instanceId; iconObj; titleText; isInitialized; //#region element properties //#endregion //#endregion constructor() { super(); this.instanceId = IconEl.instanceCount++; IconEl.instanceMap[this.instanceId] = this; } get idKey() { return `gw-icon-${this.instanceId}`; } //#region HTMLElement implementation connectedCallback() { if (this.isInitialized) { return; } this.iconObj = ns.SVGLib.Icons[this.getAttribute("iconKey")]; this.titleText = this.getAttribute("title"); if (this.hasAttribute("titleId")) { const titleEl = document.getElementById(this.getAttribute("titleId")); this.titleText = titleEl.innerText; titleEl.remove(); } this.iconDescription = this.getAttribute("description"); this.iconClasses = this.getAttribute("iconClasses"); this.iconStyle = this.getAttribute("iconStyle"); this.renderContent(); this.isInitialized = true; } //#endregion renderContent() { if (!this.iconObj) { debugger; return; } //Markup this.insertAdjacentHTML("beforebegin", `` ); this.appendChild( ns.SVGLib.createIcon( this.iconObj, this.titleText, this.iconDescription, this.iconClasses, this.iconStyle, ) ); //element properties } }; customElements.define("gw-icon", ns.IconEl); }); /** * Author: Vera Konigin * Site: https://groundedwren.neocities.org * Contact: vera@groundedwren.com * * File Description: Gizmo for reading from Google Sheets. * Neocities editor users will see a lot of linter errors in this file, but none of them are real errors. The linter just doesn't understand some modern JS. */ /** * By default, any JavaScript code written is defined in the global namespace, which means it's accessible directly under the "window" element. * If you have a lot of scripts, this can lead to clutter and naming collisions (what if two different scripts use a variable called "i"? They can inadvertently mess each other up). * To get around this, we define the registerNamespace function in the global namespace, which just confines all the code in the function passed to it to a property under window. * That property is represented as the "path" parameter. It is passed to the function for ease of access. */ function registerNamespace(path, nsFunc) { var ancestors = path.split("."); var ns = window; for(var i = 0; i < ancestors.length; i++) { ns[ancestors[i]] = ns[ancestors[i]] || {}; ns = ns[ancestors[i]]; } nsFunc(ns); } registerNamespace("GW.Gizmos", function(ns) { /** * A class to read from one page in a google sheet document */ ns.GoogleSheetsReader = class GoogleSheetsReader { //setResponse is intended for React - it's how google responds to our GET. Fortunately valid JSON is inside this call, so we can just parse it out. static #RESPONSE_PREFIX = "setResponse("; static #RESPONSE_SUFFIX = ");"; //Here we can define any custom types based on column label. "Timestamp" is intended for ISO 8601 format date/time strings. static #CUSTOM_LABEL_TYPES = { "Timestamp": "timestamp" }; spreadsheetId; //The ID of the spreadsheet. This is the part just after /d/ in the docs.google.com URL sheetName; //The name of the particular sheet we're after #sheetURL; //Composed request URL loadPromise = null; //A promise created when loading begins and which resolves when data has finished loading. tableJSON = null; //Raw JS Object version of the returned JSON. rowData = null; //Parsed row data colData = null; //A shortcut to the the column data in tableJSON colIndex = null; //An index from column label to its metadata, plus array position /** * Constructs a GoogleSheetsReader object * spreadsheetId is the part of the docs.google.com URL just after /d/ * sheetName is the name of the particular page */ constructor(spreadsheetId, sheetName) { this.spreadsheetId = spreadsheetId; this.sheetName = sheetName; this.#sheetURL = `https://docs.google.com/spreadsheets/d/${spreadsheetId}/gviz/tq?sheet=${sheetName}`; } /** * Loads and parses sheet data via HTTP GET * Returns null on success, and an error string on failure. */ async loadData() { this.loadPromise = this.#loadData(); return this.loadPromise; } async #loadData() { this.tableJSON = null; this.rowData = null; this.colData = null; this.colIndex = null; const response = await fetch(this.#sheetURL); if (response.ok) { return response.text().then((unparsedData) => { //This is parsing out the valid JSON from the React method they gave us const targetData = unparsedData.split( GoogleSheetsReader.#RESPONSE_PREFIX )[1].split( GoogleSheetsReader.#RESPONSE_SUFFIX )[0]; this.tableJSON = GoogleSheetsReader.#applyCustomLabelTypes(JSON.parse(targetData).table); this.rowData = GoogleSheetsReader.#parseAllRows(this.tableJSON); this.colIndex = GoogleSheetsReader.#indexColumns(this.tableJSON); this.colData = this.tableJSON.cols; return null; }); } else { return response.statusText || response.status; } } /** * Overrides any google-returned column data types with custom ones based on label */ static #applyCustomLabelTypes(tableJSON) { tableJSON.cols.forEach(col => { if(this.#CUSTOM_LABEL_TYPES[col.label]) { col.type = this.#CUSTOM_LABEL_TYPES[col.label] }; }); return tableJSON; } static #parseAllRows(tableJSON) { const rowDataArray = []; for(let i = 0; i < tableJSON.rows.length; i++) { rowDataArray.push(this.#parseRow(i, tableJSON)); } return rowDataArray; } static #parseRow(rowIdx, tableJSON) { const rowData = {}; const cells = tableJSON.rows[rowIdx].c; for(let i = 0; i < cells.length; i++) { rowData[tableJSON.cols[i].label] = this.#parseCellType(cells[i], tableJSON.cols[i].type); } return rowData; } /** * Parses a cell based on its type. Further custom types will need their own parsing added here. */ static #parseCellType(cellData, cellType) { switch (cellType) { case "string": return cellData ? cellData.v : cellData; case "number": return cellData ? cellData.v : cellData; case "datetime": case "date": return (cellData && cellData.v) ? eval("new " + cellData.v) : null; case "timestamp": const cellTimestamp = new Date(cellData ? cellData.v : ""); return isNaN(cellTimestamp) ? null : cellTimestamp; default: return cellData; } } static #indexColumns(tableJSON) { const colIndex = {}; for(let i = 0; i < tableJSON.cols.length; i++) { const colData = tableJSON.cols[i]; colIndex[colData.label] = {...colData, index: i}; } return colIndex; } }; }); /** * @file Comments control * @author Vera Konigin vera@groundedwren.com * https://groundedwren.neocities.org */ window.GW = window.GW || {}; (function Controls(ns) { ns.CommentForm = class CommentForm extends HTMLElement { //#region staticProperties static instanceCount = 0; static instanceMap = {}; //#endregion //#region instance properties instanceId; isInitialized; titleText; discordURL; encodedPath; fallbackEmail; //#region element properties formEl; titleEl; bannerEl; dispNameInpt; emailInpt; websiteInpt; respToInpt; commentInpt; resetBtn; submitBtn; //#endregion //#endregion constructor() { super(); this.instanceId = CommentForm.instanceCount++; CommentForm.instanceMap[this.instanceId] = this; } get idKey() { return `gw-comment-form-${this.instanceId}`; } connectedCallback() { if (this.isInitialized) { return; } this.titleText = this.getAttribute("titleText") || "Add a Comment"; this.discordURL = this.getAttribute("discordURL"); this.encodedPath = this.getAttribute("encodedPath"); this.fallbackEmail = this.getAttribute("fallbackEmail"); this.renderContent(); this.registerHandlers(); this.isInitialized = true; } renderContent() { //Markup this.innerHTML = `

${this.titleText}

Comments are manually approved
`; //element properties this.formEl = document.getElementById(`${this.idKey}-form`); this.titleEl = document.getElementById(`${this.idKey}-title`); this.bannerEl = document.getElementById(`${this.idKey}-banner`); this.dispNameInpt = document.getElementById(`${this.idKey}-dispName`); this.emailInpt = document.getElementById(`${this.idKey}-email`); this.websiteInpt = document.getElementById(`${this.idKey}-website`); this.respToInpt = document.getElementById(`${this.idKey}-respTo`); this.commentInpt = document.getElementById(`${this.idKey}-comment`); this.resetBtn = document.getElementById(`${this.idKey}-reset`); this.submitBtn = document.getElementById(`${this.idKey}-submit`); //default values this.dispNameInpt.value = localStorage.getItem("comment-name") || ""; this.emailInpt.value = localStorage.getItem("comment-email") || ""; this.websiteInpt.value = localStorage.getItem("comment-website") || ""; } //#region Handlers registerHandlers() { this.formEl.onsubmit = this.onSubmit; } onSubmit = (event) => { event.preventDefault(); const contentObj = { name: this.dispNameInpt.value, email: this.emailInpt.value, website: this.websiteInpt.value, responseTo: this.respToInpt.value, comment: ( this.commentInpt.value || "" ).replaceAll("\n", "
").replaceAll("(", "\\("), timestamp: new Date().toUTCString(), }; const contentAry = []; for (let contentKey in contentObj) { contentAry.push(`${contentKey}=${contentObj[contentKey]}`); } const request = new XMLHttpRequest(); request.open( "POST", this.discordURL || atob("aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3Mv" + this.encodedPath), true ); request.setRequestHeader("Content-Type", "application/json"); request.onreadystatechange = () => { if (request.readyState !== XMLHttpRequest.DONE) { return; } if (Math.floor(request.status / 100) !== 2) { console.log(request.responseText); this.bannerEl.classList.add("warning"); this.bannerEl.innerHTML = ` That didn't work. ${this.fallbackEmail ? `Click here to send as an email instead.` : "" } `; } else { alert("Your comment has been submitted!"); } }; request.send(JSON.stringify({ embeds: [{ fields: Object.keys(contentObj).map(key => { return { name: key, value: contentObj[key] }}) }] })); localStorage.setItem("comment-name", contentObj.name); localStorage.setItem("comment-email", contentObj.email); localStorage.setItem("comment-website", contentObj.website); this.formEl.reset(); this.dispNameInpt.value = contentObj.name; this.emailInpt.value = contentObj.email; this.websiteInpt.value = contentObj.website; }; //#endregion }; customElements.define("gw-comment-form", ns.CommentForm); ns.CommentList = class CommentList extends HTMLElement { //#region staticProperties static instanceCount = 0; static instanceMap = {}; static Data = []; //#endregion //#region instance properties instanceId; isInitialized; gSpreadsheetId; gSheetId; isNewestFirst; gwCommentFormId; //#region element properties //#endregion //#endregion constructor() { super(); this.instanceId = CommentList.instanceCount++; CommentList.instanceMap[this.instanceId] = this; CommentList.Data[this.instanceId] = {}; } get idKey() { return `gw-comment-list-${this.instanceId}`; } connectedCallback() { if (this.isInitialized) { return; } this.gSpreadsheetId = this.getAttribute("gSpreadsheetId"); this.gSheetId = this.getAttribute("gSheetId"); this.isNewestFirst = this.getAttribute("isNewestFirst"); this.gwCommentFormId = this.getAttribute("gwCommentFormId"); this.loadAndRender(); this.isInitialized = true; } async loadAndRender() { this.innerHTML = `
Comments loading....
` const sheetReader = new GW.Gizmos.GoogleSheetsReader(this.gSpreadsheetId, this.gSheetId); await sheetReader.loadData(); this.innerHTML = ""; const allComments = sheetReader.rowData; if (this.isNewestFirst) { allComments.reverse(); } this.renderContent(); this.registerHandlers(); const allCommentsIndex = {}; const topLevelCommentIdxs = []; const childCommentIdxs = []; for (let i = 0; i < allComments.length; i++) { const comment = allComments[i]; allCommentsIndex[comment.ID] = i; if (!comment.ResponseTo) { topLevelCommentIdxs.push(i); } else { childCommentIdxs.push(i); } } childCommentIdxs.forEach(childIdx => { const replyId = allComments[childIdx].ResponseTo; const respondeeComment = allComments[allCommentsIndex[replyId]]; respondeeComment.ChildIdxs = respondeeComment.ChildIdxs || []; respondeeComment.ChildIdxs.push(childIdx); }); let commentsToBuild = []; topLevelCommentIdxs.forEach( topCommentIdx => commentsToBuild.push({ parent: this.containerEl, comment: allComments[topCommentIdx] }) ); while (commentsToBuild.length > 0) { let { parent, comment } = commentsToBuild.shift(); if (!comment.Timestamp) { continue; } CommentList.Data[this.instanceId][comment.ID] = comment; parent.insertAdjacentHTML("beforeend", ` `); const commentEl = document.getElementById(`${this.idKey}-cmt-${comment.ID}`); (comment.ChildIdxs || []).forEach( childIdx => commentsToBuild.push({ parent: commentEl.articleEl, comment: allComments[childIdx] }) ); } } renderContent() { //Markup this.innerHTML = `
`; //element properties this.containerEl = document.getElementById(`${this.idKey}-container`); } //#region Handlers registerHandlers() { } //#endregion }; customElements.define("gw-comment-list", ns.CommentList); ns.CommentCard = class CommentCard extends HTMLElement { //#region staticProperties static instanceCount = 0; static instanceMap = {}; //#endregion //#region instance properties instanceId; isInitialized; commentId; gwCommentFormId; replyToId; numChildren; commenterName; datetime; websiteURL; commentText; //#region element properties articleEl; replyBtn; //#endregion //#endregion constructor() { super(); this.instanceId = CommentCard.instanceCount++; CommentCard.instanceMap[this.instanceId] = this; } get idKey() { return `gw-comment-card-${this.instanceId}`; } //#region HTMLElement implementation connectedCallback() { if (this.isInitialized) { return; } this.commentId = this.getAttribute("commentId"); this.gwCommentFormId = this.getAttribute("gwCommentFormId"); const commentData = ns.CommentList.Data[this.getAttribute("listInstance")][this.commentId]; this.replyToId = commentData.ResponseTo; this.numChildren = (commentData.ChildIdxs || []).length; this.commenterName = commentData["Display Name"]; this.datetime = commentData.Timestamp; this.websiteURL = commentData.Website; this.commentText = this.parseCommentText(commentData.Comment); this.renderContent(); this.registerHandlers(); this.isInitialized = true; } //#endregion renderContent() { let headerText = this.replyToId ? `Comment #${this.commentId} replying to #${this.replyToId}` : `Top level comment #${this.commentId}`; headerText += ` with ${this.numChildren} direct ${this.numChildren == 1 ? "reply" : "replies"}`; const displayTimestamp = this.datetime.toLocaleString( undefined, { dateStyle: "short", timeStyle: "short" } ); const commenterNameEl = this.websiteURL ? `${this.commenterName}` : `${this.commenterName}`; //Markup this.innerHTML = `
${commenterNameEl}
${this.commentText}
`; //element properties this.articleEl = document.getElementById(`${this.idKey}-article`); this.timestamp = document.getElementById(`${this.idKey}-timestamp`); this.replyBtn = document.getElementById(`${this.idKey}-reply`); this.hideBtn = document.getElementById(`${this.idKey}-hide`); this.showBtn = document.getElementById(`${this.idKey}-show`); } //#region Handlers registerHandlers() { this.replyBtn.onclick = this.onReply; this.hideBtn.onclick = this.onHide; this.showBtn.onclick = this.onShow; } onReply = () => { const gwCommentForm = document.getElementById(this.gwCommentFormId); const respToInpt = gwCommentForm.respToInpt; if (!respToInpt) { alert("Comment form not found"); return; } respToInpt.value = this.commentId; respToInpt.focus(); }; onHide = () => { this.classList.add("collapsed"); this.showBtn.focus(); }; onShow = () => { this.classList.remove("collapsed"); this.timestamp.focus(); }; //#endregion parseCommentText(commentString) { let commentText = ""; let linkObj = {}; for(let i = 0; i < commentString.length; i++){ let char = commentString.charAt(i); switch (char) { case '[': linkObj = {tStart: i}; break; case ']': if(linkObj.tStart !== undefined && linkObj.tStart !== i-1) { linkObj.tEnd = i; } else { linkObj = {}; } break; case '(': if(linkObj.tEnd !== undefined && linkObj.tEnd === i-1) { linkObj.lStart = i; } else { linkObj = {}; } break; case ')': if(linkObj.lStart !== undefined && linkObj.lStart !== i-1) { linkObj.lEnd = i; } else { linkObj = {}; } break; } if(linkObj.lEnd !== undefined) { const linkText = commentString.substring(linkObj.tStart + 1, linkObj.tEnd); const linkURL = commentString.substring(linkObj.lStart + 1, linkObj.lEnd); commentText = commentText.substring(0, commentText.length - (i - linkObj.tStart)); commentText += `${linkText}`; linkObj = {}; } else { commentText += char; } } return commentText; } }; customElements.define("gw-comment-card", ns.CommentCard); }) (window.GW.Controls = window.GW.Controls || {}); const hero = document.querySelector(".hero"); const heroTopBarEl = document.querySelector(".hero__top-bar"); const headerImgEl = document.querySelector(".hero__img"); const todayEvent = getTodayEvent(); if (todayEvent) { heroTopBarEl.classList.remove('hidden'); heroTopBarEl.innerHTML = todayEvent.blurb; if (todayEvent.class) { headerImgEl.classList.add(todayEvent.class); } } function getTodayEvent() { const date = new Date(); const month = date.getMonth() + 1; const day = date.getDate(); const year = date.getFullYear(); const weekOfMonth = Math.ceil(day / 7); const leilukinsHubLaunchDate = new Date("2022-09-11").getFullYear(); const siteAnniversary = year - leilukinsHubLaunchDate; if (month === 3 && day === 1) return { blurb: `Today is Zero Discrimination Day`, class: "flag-progress-intersex", }; else if (month === 3 && day === 8) return { blurb: `Today is International Women's Day}`, class: "symbol-venus", }; else if (month === 3 && day === 31) return { blurb: `Today is Trans Day of Visibility`, class: "flag-trans", }; else if (month === 4 && day === 6) return { blurb: `Today is International Asexuality Day`, class: "flag-ace", }; else if (month === 4 && day === 26) return { blurb: `Today is Lesbian Visibility Day`, class: "flag-lesbian", }; else if (month === 4 && weekOfMonth === 4) return { blurb: `This week is Lesbian Visibility Week`, class: "flag-lesbian", }; else if (month === 5 && day === 17) return { blurb: `Today is International Day Against Homophobia, Biphobia and Transphobia`, class: "flag-progress", }; else if (month === 5 && day === 19) return { blurb: `Today is Agender Pride Day`, class: "flag-agender", }; else if (month === 5 && day === 25) return { blurb: `Today is Pansexual and Panromantic Awareness and Visibility Day`, class: "flag-pan", }; else if (month === 6) return { blurb: `Happy Pride Month!`, class: "flag-progress-intersex", }; else if (month === 7 && day === 14) return { blurb: `Today is Non-Binary People's Day`, class: "flag-non-binary", }; else if (month === 7 && day === 28) return { blurb: `Today is Leilukin's Birthday` }; else if (month === 7) return{ blurb: `Happy Disability Pride Month!`, class: "flag-disability" } else if (month === 8 && day === 25) return { blurb: `Today is Aromantic Spectrum Visibility Day`, class: "flag-aro", }; else if (month === 9 && day === 11) return { blurb: `Today is the ${siteAnniversary}-year anniversary of the launch of Leilukin's Hub` }; else if (month === 9 && day === 23) return { blurb: `Today is Bi Visibility Day`, class: "flag-bi", }; else if (month === 10 && day === 8) return { blurb: `Today is International Lesbian Day`, class: "flag-lesbian", }; else if (month === 10 && day === 11) return { blurb: `Today is National Coming Out Day`, class: "flag-rainbow", }; else if (month === 10 && day === 17) return { blurb: `Today is the start of Genderfluid Visibility Week`, class: "flag-genderfluid", }; else if (month === 10 && day === 26) return { blurb: `Today is Intersex Awareness Day`, class: "flag-intersex", }; else if (month === 11 && day === 13) return { blurb: `Today is the start of Transgender Awareness Week`, class: "flag-trans", }; else return null; }