-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscript.js
561 lines (520 loc) · 21.7 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
/** Copyright (C) 2023 NCHUIT <[email protected]>. CC BY-NC-SA 4.0
*
* Portions of this page are modifications based on work created and
* shared by Google and used according to terms described in the
* Creative Commons 4.0 Attribution License.
*/
let 選定題庫 = '', 暫存題庫 = [], 題庫 = [], 目前題目 = [], 目前背景音樂 = new Audio(),
介面狀態, 登入狀態, 正確答案, 靜音狀態, 答對題數, 總題數;
const 時鐘 = document.getElementById("時鐘").children,
靜音切換按鈕 = document.getElementById("靜音切換按鈕"),
使用者名稱 = document.getElementById('使用者名稱'),
選單說明按鈕 = document.getElementById('選單說明按鈕'),
登入按鈕區塊 = document.getElementById('登入按鈕區塊'),
登入按鈕 = document.getElementById('登入按鈕'),
登出按鈕 = document.getElementById('登出按鈕'),
載入按鈕 = document.getElementById('載入按鈕'),
載入提示 = document.getElementById('載入提示'),
按鈕A = document.getElementById('按鈕A'),
按鈕B = document.getElementById('按鈕B'),
按鈕C = document.getElementById('按鈕C'),
按鈕D = document.getElementById('按鈕D'),
送出按鈕 = document.getElementById('送出按鈕'),
至頂按鈕 = document.getElementById('至頂按鈕'),
狀態欄 = document.getElementById('狀態欄'),
答題紀錄 = document.getElementById('答題紀錄'),
答題狀態欄 = document.getElementById('答題狀態欄'),
錯誤訊息視窗 = document.getElementById('錯誤訊息視窗'),
錯誤訊息視窗內文 = document.getElementById('錯誤訊息視窗內文'),
錯誤訊息視窗登入按鈕 = document.getElementById('錯誤訊息視窗登入按鈕'),
載入背景音樂 = document.getElementById('map_background_music'),
答題背景音樂 = document.getElementById('fight_background_music'),
正解音效 = document.getElementById('victory_sound_effect'),
錯題音效 = document.getElementById('keep_going_sound_effect'),
點擊音效 = document.getElementById('panel_btn_click_sound_effect'),
輸入框 = [
document.forms[0][0],
document.forms[0][1],
document.forms[0][2],
document.forms[0][3],
document.forms[0][4],
];
// From https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep
const sleep = (ms = 0) => new Promise(r => setTimeout(r, ms));
// From https://www.w3schools.com/js/tryit.asp?filename=tryjs_timing_clock
const 補零 = i => i < 10 ? '0' + i : i.toString(); // add zero in front of numbers < 10
function 計時() {
const t = new Date();
let hms = [t.getHours(), t.getMinutes(), t.getSeconds()];
hms = 補零(hms[0]) + 補零(hms[1]) + 補零(hms[2]);
for (const i in 時鐘) if (時鐘[i].innerHTML != hms[i]) 時鐘[i].innerHTML = hms[i];
setTimeout(計時, 1000 - new Date() % 1000);
}
function 調整介面() {
$('#說明視窗 iframe').attr("height", screen.height * .7);
for (const 元素 of 輸入框) {
元素.style.height = "auto";
元素.style.height = 元素.scrollHeight + "px";
}
if (innerWidth < 767) {
if (介面狀態 == '小') return;
介面狀態 = '小';
$('#answer-panel').addClass('attack_modal_m');
$('#answer-panel').addClass('attack_modal_m_sprite');
$('#answer-panel').removeClass('panel');
$('#answer-panel').removeClass('attack_modal_reading_sprite');
$('.input-group-area').attr('data-selection-count', 6);
$('.input-group-area .attack_modal_sprite').addClass('attack_modal_m_sprite');
$('.input-group-area .attack_modal_sprite').removeClass('attack_modal_sprite');
$('.btn04').addClass('btn04_m');
$('.btn04').removeClass('btn04');
} else {
if (介面狀態 == '大') return;
介面狀態 = '大';
$('#answer-panel').addClass('panel');
$('#answer-panel').addClass('attack_modal_reading_sprite');
$('#answer-panel').removeClass('attack_modal_m');
$('#answer-panel').removeClass('attack_modal_m_sprite');
$('.input-group-area').attr('data-selection-count', 4);
$('.input-group-area .attack_modal_m_sprite').addClass('attack_modal_sprite');
$('.input-group-area .attack_modal_m_sprite').removeClass('attack_modal_m_sprite');
$('.btn04_m').addClass('btn04');
$('.btn04_m').removeClass('btn04_m');
}
}
function 切換背景音樂(哪個 = '') {
答題背景音樂.muted = 載入背景音樂.muted = true;
目前背景音樂 = document.getElementById(哪個 + '_background_music');
if (靜音狀態 == 2) {
目前背景音樂.muted = false;
目前背景音樂.play();
}
}
function 音效播放(音效 = new HTMLAudioElement()) {
音效.currentTime = 0;
音效.play();
}
function 靜音切換() {
switch (靜音狀態) {
default:
case 0: 靜音狀態 = 1;
靜音切換按鈕.innerHTML = `<i class="fa fa-volume-down"></i>`;
靜音切換按鈕.setAttribute("data-tooltip","僅點選音效");
正解音效.muted = 錯題音效.muted = 點擊音效.muted = false;
return 1;
case 1: 靜音狀態 = 2;
靜音切換按鈕.innerHTML = `<i class="fa fa-volume-up"></i>`;
靜音切換按鈕.setAttribute("data-tooltip","播放背景音樂");
目前背景音樂.muted = false;
目前背景音樂.play();
return 2;
case 2: 靜音狀態 = 0;
靜音切換按鈕.innerHTML = `<i class="fa fa-volume-mute"></i>`;
靜音切換按鈕.setAttribute("data-tooltip","靜音");
正解音效.muted = 錯題音效.muted = 點擊音效.muted = true;
目前背景音樂.muted = true;
return 0;
}
}
let 使用者;
/** From https://developers.google.com/sheets/api/quickstart/js
* Called when the signed in status changes, to update the UI
* appropriately. After a sign-in, the API is called.
*/
function 更新登入狀態(isSignedIn = Boolean(gapi.client.getToken()), 只是看看 = false) {
載入按鈕.style.display = 'none';
if (isSignedIn) {
登入按鈕.style.display = 'none';
登出按鈕.style.display = 'block';
if (只是看看) return isSignedIn;
重載題庫();
} else {
登入按鈕.style.display = 'block';
登出按鈕.style.display = 'none';
}
// From https://developers.google.com/identity/gsi/web/reference/js-reference#CredentialResponse
if (gapi.client.getToken()) {
使用者名稱.innerHTML = 使用者.name;
選單說明按鈕.innerHTML = `<i><img src="${使用者.picture}"></i>`;
登入按鈕區塊.setAttribute("data-tooltip", "已登入 " + 使用者.email);
} else {
使用者名稱.innerHTML = "登出";
選單說明按鈕.innerHTML = `<i class="fa fa-question-circle"></i>`;
登入按鈕區塊.setAttribute("data-tooltip", "登入 Google 帳號 以存取試算表");
}
return isSignedIn;
}
// From https://stackoverflow.com/a/12646864/13189986
function 打亂陣列(陣列 = []) {
for (let i = 陣列.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[陣列[i], 陣列[j]] = [陣列[j], 陣列[i]];
}
return 陣列;
}
function 下一題() {
載入提示.style.display = 'flex';
$('#送出按鈕').hide();
$('#下一題按鈕').show()
document.getElementById('answer-panel-question-content').scrollTo(0, 0);
if (暫存題庫.length < 1 && !更新登入狀態()) 登入();
目前題目 = 暫存題庫.pop();
輸入框[0].value = 輸入框[0].innerHTML = 目前題目[0];
正確答案 = String(目前題目[1]);
目前題目 = 打亂陣列(目前題目.slice(1));
for (const 元素 of 輸入框.slice(1))
元素.value = 元素.innerHTML = 目前題目.pop();
for (const i in 輸入框) 目前題目[i] = 輸入框[i].innerHTML;
切換背景音樂('fight');
調整介面();
載入提示.style.display = 'none';
}
async function 檢查答案(選項 = new HTMLElement()) {
if (送出按鈕.style.display == 'none') {
if (正確答案 === 選項.value || 正確答案 === 選項.innerHTML) {
錯題音效.pause();
音效播放(正解音效);
await sleep(50);
if (confirm('⭕答對啦!\n\n' + 正確答案 + '\n\n按下取消(Esc)返回、確定(Enter)下一題')){
下一題();
++答對題數;
更新答題狀態欄();
}
} else {
正解音效.pause();
音效播放(錯題音效);
更新答題狀態欄();
}
} else {
for (const 元素 of 輸入框.slice(1)) {
if (元素.value == 選項.value || 元素.innerHTML == 選項.innerHTML) {
[輸入框[1].value, 輸入框[1].innerHTML, 選項.value, 選項.innerHTML] =
[選項.value, 選項.innerHTML, 輸入框[1].value, 輸入框[1].innerHTML];
}
}
調整介面();
}
}
// From https://developers.google.com/sheets/api/quickstart/js
function 狀態欄續寫(訊息 = '') {
狀態欄.appendChild(document.createTextNode(訊息 + '\n'));
return 訊息;
}
function 更新答題狀態欄(
訊息 = `👉目前答題進度(${暫存題庫.length}/${總題數}) ⭕答對 ${答對題數} 題 🎯命中率 ${((答對題數/(總題數-暫存題庫.length+1))*100).toFixed(1)}%`) {
答題狀態欄.innerHTML = 訊息 + '\n';
return 訊息;
}
function 重設狀態欄(訊息 = `👉「${選定題庫}」目前題庫有${總題數=題庫.length}題(新到舊)`) {
狀態欄.innerHTML = 訊息 + '\n';
return 訊息;
}
function 彈出錯誤訊息(訊息 = '') {
重設狀態欄('⚠️錯誤訊息');
狀態欄續寫(訊息);
錯誤訊息視窗內文.innerHTML = 訊息;
$('#錯誤訊息視窗').modal('show');
錯誤訊息視窗.style.left = 'unset';
return 訊息;
}
// From https://developers.google.com/sheets/api/quickstart/js
async function 重載題庫() {
輸入框[1].parentElement.parentElement.removeAttribute('data-correct');
載入提示.style.display = 'flex';
選定題庫 = '';
$('#選擇視窗').modal('show');
if(答對題數>0) 答題紀錄.innerHTML +=
`[${new Date().toLocaleString()}] ${選定題庫} ⭕答對 ${答對題數}/${總題數} 題 🎯命中率 ${((答對題數/總題數)*100).toFixed(1)}%`
while (!選定題庫) {
$('#選擇視窗').modal('show');
await sleep(50);
}
重設狀態欄();
gapi.client.sheets.spreadsheets.values.get({
spreadsheetId: '1mLuYzFZp-zuLn1w8OMAo9XT99kzyMYVd3Zq299FYNlw', // Real
// spreadsheetId: '1o6qXeil50N9-J_ONMDZybYeHt1aZ9ReSIFwtVnRYk4E', // Test
range: 選定題庫 + '!B2:F',
}).then(function (response) {
載入提示.style.display = 'flex';
var range = response.result;
if (range.values.length > 0) {
題庫 = 暫存題庫 = range.values;
重設狀態欄();
題庫.reverse();
const 欄位標題 = ['🤔', '⭕正確答案: ', '錯誤答案1: ', '錯誤答案2: ', '錯誤答案3: '];
for (const row of 題庫)
for (const i in 欄位標題)
狀態欄續寫('\n' + 欄位標題[i] + row[i]);
打亂陣列(暫存題庫);
下一題();
答對題數 = 0;
} else 彈出錯誤訊息('No data found.');
}, 回應 => 彈出錯誤訊息('Error: ' + 回應.result.error.message));
}
async function 登入() {
載入提示.style.display = 'flex';
載入按鈕.style.display = 'block';
登入按鈕.style.display = 'none';
切換背景音樂('map');
const token = gapi.client.getToken();
if (token === null) {
// Prompt the user to select a Google Account and ask for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
更新登入狀態();
}
function 清除輸入框() {
切換背景音樂('map');
document.forms[0].reset();
for (input of document.forms[0])
input.value = input.innerHTML = null;
調整介面();
$('#送出按鈕').hide();
$('#下一題按鈕').show();
}
function 送出題目() {
if (!gapi.client.getToken()) return 彈出錯誤訊息('未登入');
if (送出按鈕.style.display == 'none' || 檢查題目()) return;
else if (confirm(輸入框[1].value + '\n\n是正確答案嗎?\n\n按下確定(Enter)送至 Google 試算表')) {
document.forms[0].submit();
$('#送出按鈕').hide()
$('#下一題按鈕').show();
更新登入狀態();
}
}
function 檢查題目() {
const value = 輸入框[0].value;
const innerHTML = 輸入框[0].innerHTML;
for (const row of 題庫)
if ((value && value.length > 5
&& String(row[0]).indexOf(value) > -1)
|| (innerHTML && innerHTML.length > 5
&& String(row[0]).indexOf(innerHTML) > -1)) {
if (!confirm(`有這個題目了,檢查正確答案無誤?
⭕正確答案: ${row[1]}
錯誤答案1: ${row[2]}
錯誤答案2: ${row[3]}
錯誤答案3: ${row[4]}
按下取消(Esc)以關閉,確定(Enter)以編輯/送出修改
👉記得到試算表刪掉原來錯的,自動刪除開發中...`)) return true;
else break;
}
return false;
}
function 輸入() {
切換背景音樂('map');
let content = String(輸入框[0].value);
let ai = content.indexOf('\nA\n');
let bi = content.indexOf('\nB\n', ai);
let ci = content.indexOf('\nC\n', bi);
let di = content.indexOf('\nD\n', ci);
let ans = [
content.substring(ai + 3, bi),
content.substring(bi + 3, ci),
content.substring(ci + 3, di),
content.substring(di + 3)
];
if (ai > 5) 輸入框[0].value = content.substring(0, ai);
if (檢查題目()) {
for (const i in 輸入框)
輸入框[i].value = 輸入框[i].innerHTML = 目前題目[i];
$('#送出按鈕').hide();
$('#下一題按鈕').show()
輸入框[1].parentElement.parentElement.removeAttribute('data-correct');
} else if (ai > -1 && bi > -1 && ci > -1 && di > -1) {
$('#下一題按鈕').hide();
$('#送出按鈕').show();
輸入框[1].parentElement.parentElement.setAttribute('data-correct', 'true');
let temp;
const tip = `
這是正確答案嗎?
按下取消(Esc)選為錯誤答案、確定(Enter)選為正確答案`;
for (let i = -1; !confirm((temp = ans[++i]) + tip);)
if (i == 2) { temp = ans[3]; break; }
ans.splice(ans.indexOf(temp), 1);
輸入框[1].value = temp;
for (const i of Array(3).keys())
輸入框[2 + i].value = 輸入框[2 + i].innerHTML = ans[i];
} else if (
(輸入框[1].value || 輸入框[1].innerHTML) &&
(輸入框[2].value || 輸入框[2].innerHTML) &&
(輸入框[3].value || 輸入框[3].innerHTML) &&
(輸入框[4].value || 輸入框[4].innerHTML)
) {
$('#下一題按鈕').hide();
$('#送出按鈕').show();
輸入框[1].parentElement.parentElement.setAttribute('data-correct', 'true');
}
調整介面();
}
// EventListener
document.getElementById('清除按鈕').onclick = 清除輸入框;
document.getElementById('下一題按鈕').onclick = 下一題;
document.getElementById('選單說明按鈕').onclick =
document.getElementById('驚嘆號按鈕').onclick = e => $('#說明視窗').modal('show');
document.getElementById('選擇視窗按鈕1').onclick = e => {
選定題庫 = '實際初賽題目';
document.forms[0].setAttribute("action", "https://docs.google.com/forms/u/1/d/e/1FAIpQLSeqkw8jflmdbSgiEbjodnfLw5zEDebYxzMT0V9gTpOb8wjyTQ/formResponse");
document.forms[0][0].setAttribute("name", "entry.1911469271");
document.forms[0][1].setAttribute("name", "entry.1072618664");
document.forms[0][2].setAttribute("name", "entry.1728754073");
document.forms[0][3].setAttribute("name", "entry.1621978531");
document.forms[0][4].setAttribute("name", "entry.1926198241");
}
document.getElementById('選擇視窗按鈕2').onclick = e => {
選定題庫 = '大雜燴';
document.forms[0].setAttribute("action", "https://docs.google.com/forms/u/1/d/e/1FAIpQLSc8J8l55WOGCbYfQlc3vA6sr-6TD7pPsFioW_bZCaTTVOjnWA/formResponse");
document.forms[0][0].setAttribute("name", "entry.892031688");
document.forms[0][1].setAttribute("name", "entry.977089316");
document.forms[0][2].setAttribute("name", "entry.657500498");
document.forms[0][3].setAttribute("name", "entry.1532072947");
document.forms[0][4].setAttribute("name", "entry.1090409630");
}
送出按鈕.onclick = 送出題目;
靜音切換按鈕.onclick = 靜音切換;
登入按鈕.onclick = 錯誤訊息視窗登入按鈕.onclick = 登入;
按鈕A.onclick = e => 檢查答案(輸入框[1]);
按鈕B.onclick = e => 檢查答案(輸入框[2]);
按鈕C.onclick = e => 檢查答案(輸入框[3]);
按鈕D.onclick = e => 檢查答案(輸入框[4]);
登出按鈕.onclick = e => {
登出按鈕.style.display = 'none';
載入按鈕.style.display = 'block';
載入提示.style.display = 'flex';
const token = gapi.client.getToken();
if (token !== null) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
}
// From https://stackoverflow.com/questions/179355/clearing-all-cookies-with-javascript
for (const cookie of document.cookie.split(";")) { // Clearing all cookies
const eqPos = cookie.indexOf("=");
const name = eqPos > -1 ? cookie.substring(0, eqPos) : cookie;
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
}
重設狀態欄('👉目前題庫(您已登出)');
切換背景音樂('map');
暫存題庫 = 題庫 = 目前題目 = 正確答案 = [];
清除輸入框();
更新登入狀態(false);
google.accounts.id.prompt();
};
載入按鈕.onclick = 載入提示.onclick = e => {
if (更新登入狀態()) 重載題庫();
};
// When the user clicks on the button, scroll to the top of the document
至頂按鈕.onclick = e => {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
};
// From https://stackoverflow.com/questions/13623280/onclick-select-whole-text-textarea
for (const 元素 of 輸入框) {
元素.addEventListener("input", 輸入);
元素.onfocus = e => {
元素.select();
// Work around Chrome's little problem
元素.onmouseup = function () {
// Prevent further mouseup intervention
元素.onmouseup = null;
return false;
};
};
}
onload = onresize = 調整介面;
onfocus = e => {
更新登入狀態(gapi.client.getToken(), true);
調整介面();
if (載入提示.style.display != 'none') 輸入框[0].focus();
};
onblur = e => {
調整介面();
登入按鈕.style.display = 登出按鈕.style.display = 'none';
載入按鈕.style.display = 'block';
}
// from https://www.w3schools.com/howto/howto_js_scroll_to_top.asp
// When the user scrolls down 20px from the top of the document, show the button
onscroll = e => {
if (document.body.scrollTop > innerHeight
|| document.documentElement.scrollTop > innerHeight) {
至頂按鈕.style.display = "block";
} else {
至頂按鈕.style.display = "none";
}
};
document.body.onclick = e => 音效播放(點擊音效);
document.body.onkeydown = e => {
if (e.target == document.body) switch (e.key.toUpperCase()) {
default:
break; case ' ': e.preventDefault(); 下一題();
break; case '1': case 'A': 按鈕A.click();
break; case '2': case 'B': 按鈕B.click();
break; case '3': case 'C': 按鈕C.click();
break; case '4': case 'D': 按鈕D.click();
break; case 'M': 靜音切換按鈕.click();
}
};
/** Set after https://accounts.google.com/gsi/client are loaded.*/
let tokenClient = google.accounts.oauth2.initTokenClient({
/**Client ID from the Developer Console*/
client_id: '289902636224-oro06s681gdgk1kqrv8o1oca2shocfr4.apps.googleusercontent.com',
// Authorization scopes required by the API; multiple scopes can be included, separated by spaces.
scope: 'https://www.googleapis.com/auth/spreadsheets.readonly',
callback : async (resp) => {
console.log(resp);
if (resp.error !== undefined) {
彈出錯誤訊息('Error: ' + 回應.error.message);
throw (resp);
}
// Handle the initial sign-in state.
if (!更新登入狀態()) 登入();
},
});;
// From https://developers.google.com/sheets/api/quickstart/js
/** Run after https://apis.google.com/js/api.js is loaded. */
gapi.load('client', {
/** Callback after the API client is loaded. Loads the discovery doc to initialize the API. */
callback: async function initializeGapiClient() {
await gapi.client.init({
/**API key from the Developer Console*/
apiKey: 'AIzaSyCRfe3-dnm9GGMH_PFm9m5WHBMb_8U9HXY',
/**Discovery doc URL for APIs used by the quickstart*/
discoveryDocs: ['https://sheets.googleapis.com/$discovery/rest?version=v4'],
});
},
onerror: function() {
// Handle loading error.
alert('gapi.client failed to load!');
},
timeout: 5000, // 5 seconds.
/** Handle timeout. */
ontimeout: function() {
alert('gapi.client could not load in a timely manner!');
},
});
// From https://developers.google.com/identity/gsi/web/guides/display-button#javascript
google.accounts.id.initialize({
client_id: "289902636224-oro06s681gdgk1kqrv8o1oca2shocfr4.apps.googleusercontent.com",
callback: function handleCredentialResponse(response) {
console.log("Encoded JWT ID token: ");
// https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library
console.log(使用者 = JSON.parse(decodeURIComponent(atob(response.credential.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')).split('').map(
c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join(''))));
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and ask for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
}
});
google.accounts.id.prompt(); // also display the One Tap dialog
靜音切換(); 調整介面(); 計時();