taler-merchant-demos

Python-based Frontends for the Demonstration Web site
Log | Files | Refs | README | LICENSE

base.gohtml (6151B)


      1 {{define "base"}}<!DOCTYPE html>
      2 <html lang="{{.Lang}}">
      3 <head>
      4   <meta charset="utf-8">
      5   <meta name="viewport" content="width=device-width, initial-scale=1">
      6   <title>{{.Title}}</title>
      7   <link rel="stylesheet" type="text/css" href="{{.StaticPrefix}}demo.css">
      8   {{range .Styles}}<link rel="stylesheet" type="text/css" href="{{$.StaticPrefix}}{{.}}">{{end}}
      9   <script>
     10     document.addEventListener("DOMContentLoaded", function () {
     11       const button = document.getElementById("language-button");
     12       const menu = document.getElementById("language-menu");
     13       function closeMenu() {
     14         menu.hidden = true;
     15         button.setAttribute("aria-expanded", "false");
     16       }
     17       button.addEventListener("click", function (event) {
     18         const willOpen = menu.hidden;
     19         menu.hidden = !willOpen;
     20         button.setAttribute("aria-expanded", String(willOpen));
     21         event.stopPropagation();
     22       });
     23       menu.addEventListener("click", function (event) { event.stopPropagation(); });
     24       document.addEventListener("click", closeMenu);
     25       document.addEventListener("keydown", function (event) {
     26         if (event.key === "Escape" && !menu.hidden) {
     27           closeMenu();
     28           button.focus();
     29         }
     30       });
     31 
     32       const editionInfoButton = document.getElementById("edition-info-button");
     33       const editionInfo = document.getElementById("edition-info");
     34       if (editionInfoButton && editionInfo) {
     35         editionInfoButton.addEventListener("click", function () {
     36           editionInfo.showModal();
     37         });
     38         editionInfo.addEventListener("click", function (event) {
     39           if (event.target !== editionInfo) return;
     40           const bounds = editionInfo.getBoundingClientRect();
     41           const inside = event.clientX >= bounds.left && event.clientX <= bounds.right &&
     42             event.clientY >= bounds.top && event.clientY <= bounds.bottom;
     43           if (!inside) editionInfo.close();
     44         });
     45       }
     46 
     47       document.querySelectorAll("[data-copy-value]").forEach(function (copyButton) {
     48         copyButton.addEventListener("click", async function () {
     49           const value = copyButton.getAttribute("data-copy-value");
     50           const status = document.getElementById(copyButton.getAttribute("aria-describedby"));
     51           try {
     52             if (navigator.clipboard && window.isSecureContext) {
     53               await navigator.clipboard.writeText(value);
     54             } else {
     55               const input = document.createElement("textarea");
     56               input.value = value;
     57               input.setAttribute("readonly", "");
     58               input.style.position = "fixed";
     59               input.style.opacity = "0";
     60               document.body.appendChild(input);
     61               input.select();
     62               const copied = document.execCommand("copy");
     63               input.remove();
     64               if (!copied) throw new Error("copy failed");
     65             }
     66             status.hidden = false;
     67           } catch (error) {
     68             window.prompt(copyButton.getAttribute("data-copy-prompt"), value);
     69           }
     70         });
     71       });
     72     });
     73   </script>
     74 </head>
     75 <body class="demo-page demo-{{.Active}}">
     76   <a href="#main" class="skip-link">{{tr .Lang "Skip to main content"}}</a>
     77   <header class="site-header">
     78     <div class="header-inner">
     79       <div class="heading-lockup">
     80         <a class="taler-brand" href="https://taler.net/">
     81           <picture>
     82             <source srcset="{{.StaticPrefix}}taler-logo-dark.svg" media="(prefers-color-scheme: dark)">
     83             {{/* Translators: Alternative text for the GNU Taler brand logo. */}}
     84             <img src="{{.StaticPrefix}}taler-logo-light.svg" alt="{{tr .Lang "GNU Taler logo"}}" width="1000" height="448">
     85           </picture>
     86         </a>
     87         <div class="demo-heading">
     88           <h1><a href="{{.HeaderURL}}">{{.HeaderTitle}}</a></h1>
     89           <p>{{.HeaderText}}</p>
     90         </div>
     91       </div>
     92     </div>
     93   </header>
     94   <div class="nav-shell">
     95     <div class="nav-inner">
     96       <nav class="demo-nav">
     97         {{/* Translators: Name of the introductory demo page, used as a navigation label. */}}
     98         <a href="{{.Links.Landing}}" {{if eq .Active "landing"}}class="active" aria-current="page"{{end}}>{{tr .Lang "Introduction"}}</a>
     99         {{/* Translators: Navigation label for the demo bank. */}}
    100         <a href="{{.Links.Bank}}" {{if eq .Active "bank"}}class="active" aria-current="page"{{end}}>{{tr .Lang "Bank"}}</a>
    101         {{/* Translators: Name of the demo shop that sells individual essays. */}}
    102         <a href="{{.Links.Blog}}" {{if eq .Active "blog"}}class="active" aria-current="page"{{end}}>{{tr .Lang "Essay Shop"}}</a>
    103         {{/* Translators: Name of the donations demo page, used as a navigation label. */}}
    104         <a href="{{.Links.Donations}}" {{if eq .Active "donations"}}class="active" aria-current="page"{{end}}>{{tr .Lang "Donations"}}</a>
    105       </nav>
    106       <div class="language-switcher">
    107         <button class="language-button" id="language-button" type="button" aria-controls="language-menu" aria-expanded="false">{{.LanguageName}}</button>
    108         <div class="language-menu" id="language-menu" hidden>
    109           {{range .Languages}}{{if ne .Code $.Lang}}<a href="{{$.Prefix}}/{{.Code}}/">{{.Name}}</a>{{end}}{{end}}
    110         </div>
    111       </div>
    112     </div>
    113   </div>
    114   <main id="main" class="content">
    115     {{template "content" .}}
    116   </main>
    117   <footer class="site-footer">
    118     <div class="footer-inner">
    119       <p><a href="{{talerURL .Lang}}">{{tr .Lang "Learn more about GNU Taler"}}</a>.</p>
    120       <p>Copyright &copy; 2014&mdash;2026 Taler Systems SA</p>
    121     </div>
    122   </footer>
    123 </body>
    124 </html>{{end}}
    125 
    126 {{define "link-icon"}}<svg class="link-icon" aria-hidden="true" focusable="false" viewBox="0 0 16 16">
    127     <path fill-rule="evenodd" d="M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5"/>
    128     <path fill-rule="evenodd" d="M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0z"/>
    129 </svg>{{end}}