]> gitweb.michael.orlitzky.com - charm-bypass.git/blob - index.html.in
index.html.in: don't blink the expiration date/time after 10 minutes
[charm-bypass.git] / index.html.in
1 <!doctype html>
2 <html lang="en-US">
3 <head>
4 <meta name="viewport" content="width=device-width, initial-scale=1" />
5
6 <title>
7 CharmBypass.
8 </title>
9
10 <style>
11 /*
12 * Reset styles for the html and body elements, the only two HTML
13 * elements we use. */
14 html, body {
15 margin: 0;
16 padding: 0;
17 border: 0;
18 font-weight: normal;
19 font-style: inherit;
20 font-size: 100%;
21 line-height: 1.5;
22 font-family: inherit;
23 text-align: inherit;
24 text-decoration: none;
25 vertical-align: baseline;
26 background: transparent;
27 }
28
29 html, body {
30 /* To create our "window" onto the scene, we're going to slide the
31 * SVG off the left-hand side of the screen, and we don't want
32 * scroll bars to appear. */
33 overflow: hidden;
34 }
35
36 svg {
37 /* Set the height to 100% of the screen, which we'll keep; and the
38 * initial position to (0,0), which we're going to change
39 * every time the window is resized, because the exact amount
40 * that we have to slide the SVG to the left to get the ticket
41 * into the center will change. */
42 position: fixed;
43 top: 0;
44 left: 0;
45 height: 100%;
46 }
47
48 /* The blinking fade in/out animation for the ticket date and time */
49 @keyframes blink {
50 25% {
51 opacity: 0.5;
52 }
53 50% {
54 opacity: 0;
55 }
56 75% {
57 opacity: 0.5;
58 }
59 }
60
61 #tickettime, #ticketdate {
62 /* 300 two-second blinks is ten minutes */
63 animation: blink 2s linear 300;
64 }
65
66 /* Define, load, and specify the custom font we use for the ticket
67 * date, time, and service name. */
68 @font-face {
69 font-family: "CharmBypass Regular";
70 src:
71 url("data:font/woff2;base64,@CBPREGULAR@") format("woff2")
72 }
73
74 #servicename, #tickettime, #ticketdate {
75 font-family: "CharmBypass Regular";
76 }
77
78 @font-face {
79 font-family: "CharmBypass Bold";
80 src:
81 url("data:font/woff2;base64,@CBPBOLD@") format("woff2")
82 }
83
84 #serviceletter {
85 font-family: "CharmBypass Bold";
86 }
87
88 /************************/
89 /* Scrolling animations */
90 /************************/
91
92 /* Bus */
93 @keyframes busroll {
94 from {
95 transform: translateX(0%);
96 }
97 to {
98 transform: translateX(100%);
99 }
100 }
101
102 #bus {
103 animation: busroll 23s linear infinite;
104 }
105
106
107 /* Tram */
108 @keyframes tramroll {
109 from {
110 transform: translateX(0%);
111 }
112 to {
113 transform: translateX(100%);
114 }
115 }
116
117 #tram {
118 animation: tramroll 17s linear infinite;
119 }
120
121
122 /* Tram */
123 @keyframes trainroll {
124 from {
125 transform: translateX(0%);
126 }
127 to {
128 transform: translateX(100%);
129 }
130 }
131
132 #train {
133 animation: trainroll 11s linear infinite;
134 }
135
136
137 /* Clouds */
138 @keyframes cloudsfloat {
139 from {
140 transform: translateX(0%);
141 }
142 to {
143 transform: translateX(-50%);
144 }
145 }
146
147 #clouds {
148 animation: cloudsfloat 40s linear infinite;
149 }
150
151 @keyframes cloudscopyfloat {
152 from {
153 transform: translateX(0%);
154 }
155 to {
156 transform: translateX(-50%);
157 }
158 }
159
160 #cloudscopy {
161 animation: cloudscopyfloat 40s linear infinite;
162 }
163
164
165 /* Trees */
166 @keyframes treespass {
167 from {
168 transform: translateX(0%);
169 }
170 to {
171 transform: translateX(-50%);
172 }
173 }
174
175 #trees {
176 /* The trees move a little faster than the clouds */
177 animation: treespass 30s linear infinite;
178 }
179
180 @keyframes treescopypass {
181 from {
182 transform: translateX(0%);
183 }
184 to {
185 transform: translateX(-50%);
186 }
187 }
188
189 #treescopy {
190 /* The trees move a little faster than the clouds */
191 animation: treescopypass 30s linear infinite;
192 }
193
194
195 /* City skyline */
196 @keyframes cityscroll {
197 from {
198 transform: translateX(0%);
199 }
200 to {
201 transform: translateX(-50%);
202 }
203 }
204
205 #city {
206 /* The city moves faster than the clouds but slower
207 * than the trees */
208 animation: cityscroll 35s linear infinite;
209 }
210
211 @keyframes citycopyscroll {
212 from {
213 transform: translateX(0%);
214 }
215 to {
216 transform: translateX(-50%);
217 }
218 }
219
220 #citycopy {
221 /* The city moves faster than the clouds but slower
222 * than the trees */
223 animation: citycopyscroll 35s linear infinite;
224 }
225 </style>
226 </head>
227
228 <body>
229 @SVGDATA@
230
231 <script>
232 /******************************************/
233 /* First, set up the ticket date and time */
234 /******************************************/
235
236 /* There are two parameters, time and date, that we store in one
237 * underlying "date" variable. Default both to an hour and a
238 * half from now. This is what the CharmPass app does for
239 * one-way tickets.
240 */
241 const date = new Date();
242
243 /* Add an hour and a half. We use the low-level get/setTime to
244 * change the number of milliseconds since the epoch that this
245 * date represents. Obviously correct, and avoids all suspicious
246 * corner cases (well, for a few more decades). */
247 date.setTime(date.getTime() + (90*60*1000));
248
249 /* All <text> elements produced by inkscape contain a single <tspan>
250 * that itself contains the actual text. */
251 tt = document.getElementById("tickettime");
252 tt.firstChild.textContent = date.toLocaleTimeString();
253
254 const td = document.getElementById("ticketdate");
255 const dateopts = {
256 day: "2-digit",
257 month: "2-digit",
258 year: "2-digit"
259 };
260 td.firstChild.textContent = date.toLocaleDateString("en-US", dateopts);
261
262
263 /************************************************************/
264 /* Second, add the onclick handler for the night/day switch */
265 /************************************************************/
266
267 /* We always start in "day" mode */
268 is_day = true;
269
270 function set_day() {
271 sky.style.fill = "#efb02f";
272 }
273
274 function set_night() {
275 sky.style.fill = "#143b66";
276 }
277
278 function swap_colors() {
279 if (is_day) {
280 set_night();
281 is_day = false;
282 }
283 else {
284 set_day();
285 is_day = true;
286 }
287 }
288
289 document.body.addEventListener("click", swap_colors);
290
291
292 /*************************************************/
293 /* Finally, center the ticket within the browser */
294 /*************************************************/
295 function center_ticket() {
296 /* We're relying on the SVG being the full height of the
297 * viewport already, and on the aspect ratio being
298 * preserved. First, find the center of the ticket. */
299 const r = document.getElementById("ticket").getBoundingClientRect();
300 const c = r.left + (r.width / 2);
301
302 /* That's the center-line of the ticket. We want to move it to
303 * the center-line of the viewport. */
304 const vc = document.documentElement.clientWidth / 2;
305
306 /* This is how much we need to translate the SVG */
307 const delta = vc - c;
308
309 /* But before we can set the absolute left-coordinate of the
310 * SVG, we need to know where it is now. Note: without the
311 * "px" this doesn't default to pixels like CSS does. */
312 const svg = document.querySelector("svg");
313 svg.style.left = (svg.getBoundingClientRect().left + delta) + "px";
314 }
315
316 /* Re-center it when the window is resized */
317 window.addEventListener("resize", center_ticket);
318
319 /* Center it once when the page has loaded, too */
320 window.addEventListener("load", center_ticket);
321 </script>
322 </body>
323 </html>