<xmp>.</xmp> <!-- framebuster code ends here --> <!-- for ng4 --> <app-root> <div class="loading-ball-anim"> <div class="ball" style="background-color:#4285F5"></div> <div class="ball" style="background-color:#EA4436;animation-delay:.25s" ></div> <div class="ball" style="background-color:#FBBD06;animation-delay:.5s" ></div> <div class="ball" style="background-color:#34A952;animation-delay:.75s" ></div> </div> </app-root> <script> setTimeout(function() { document.querySelector('.loading-ball-anim').classList.add('start'); }, 100); </script> <!-- for angularJS --> <div id="app" class="loading"> <div class="main-ctrl" ng-controller="main as mainCtrl"> <ui-view class="main-view-container"></ui-view> </div> </div> <div id="gated-signin" class="boxed-takeover"> <div id="signinMethod" class="box auth-box"> <h1> 登入或是建立帳號 </h1> <p> To register for events </p> <button class="auth blue" onclick="signIn()"> 以Google繼續 </button> <button onclick="signInStep('enterEmail')" class="outline auth"> 以email繼續 </button> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a > </div> </div> <div id="enterEmail" class="box hidden auth-box"> <h1> 以電子郵箱登入 </h1> <div class="input-container"> <label for="emailAddress"> 輸入你的電子郵箱 </label> <input type="email" id="emailAddress" oninput="hideErrors('invalid-email')" /> <div class="error-container hidden" id="invalid-email"> <i class="google-material-icons">info</i> <span> <output>輸入有效的電子郵箱</output> </span> </div> </div> <div class="sign-in-buttons"> <div class="auth link"> <button type="button" onclick="signInStep('signinMethod')" class="button-link"> 回到上一步 </button> </div> <button class="auth blue" onclick="checkEmail()"> 下一步 </button> </div> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a> </div> </div> <div id="hasGoogleAccount" class="box hidden auth-box"> <h1> 用Google帳戶登入 </h1> <p> <output>看起來你已經使用了這個電子郵箱。請登入你的Google帳戶,繼續登入程序。</output> </p> <div class="sign-in-buttons"> <div class="auth link"> <button type="button" onclick="signInStep('enterEmail')" class="button-link"> 回到上一步 </button> </div> <button class="auth blue" onclick="signIn()"> 使用Google帳戶登入 </button> </div> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a> </div> </div> <div id="enterPassword" class="box hidden auth-box"> <form> <h1> 以電子郵箱登入 </h1> <p id="loginEmail" class="email"></p> <div class="input-container" id="password-container"> <label for="loginPassword"> 輸入你的密碼 </label> <input type="password" autocomplete="current-password" id="loginPassword" oninput="hideErrors('no-password', 'invalid-password')" required /> <div id="no-password" class="error-container hidden"> <i class="google-material-icons">info</i> <span> <output>輸入密碼</output> </span> </div> <div id="invalid-password" class="error-container hidden"> <i class="google-material-icons">info</i> <span> <output>密碼錯誤。請再試一次,或是點選「忘記密碼」來重置密碼。</output> </span> </div> </div> <div class="error-takeover hidden" id="login-retry-limit"> <div> <i class="google-material-icons">report_problem</i> <h2> 太多次登入失敗 </h2> </div> <p class="error-message"> <output>因為系統偵測到多次登入失敗,目前無法使用。請過幾分鐘後重試。</output> </p> </div> <div class="sign-in-buttons"> <div class="auth link forgot-password"> <button type="button" onclick="signInStep('resetPassword')" class="button-link"> 忘記密碼? </button> </div> <div class="auth link right-anchor"> <button type="button" onclick="signInStep('enterEmail')" class="button-link"> 回到上一步 </button> </div> <button type="button" class="auth blue" onclick="signInEmailPassword()" id="password-sign-in" > 下一步 </button> </div> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a> </div> </form> </div> <div id="createAccount" class="box auth-box hidden"> <form> <h1> 建立帳戶 </h1> <div class="input-container"> <label for="accountEmail">Email Address:</label> <input type="email" id="accountEmail" autocomplete="new-username" oninput="hideErrors('email-in-use')" disabled /> <div id="email-in-use" class="error-container hidden"> <i class="google-material-icons">info</i> <span> <output>這個電子郵箱已有人使用。請回上一步,選擇不同的電子郵箱。</output> </span> </div> </div> <div class="input-container"> <label for="accountPassword"> 輸入你的密碼 </label> <input type="password" autocomplete="new-password" id="accountPassword" oninput="hideErrors('create-account-no-password', 'weak-password')" /> <div id="create-account-no-password" class="error-container hidden"> <i class="google-material-icons">info</i> <span> <output>輸入密碼</output> </span> </div> <div id="weak-password" class="error-container hidden"> <i class="google-material-icons">info</i> <span> <output>選擇6個字元以上的密碼,包含字母、數字與特殊字元</output> </span> </div> </div> <div class="input-pair"> <div class="input-container"> <label for="accountFirstName"> 名字(不含姓氏) </label> <input type="text" id="accountFirstName" oninput="hideErrors('no-first-name')" /> <div id="no-first-name" class="error-container hidden"> <i class="google-material-icons">info</i> <span> <output>輸入名字(不含姓氏)</output> </span> </div> </div> <div class="input-container"> <label for="accountLastName"> 姓氏 </label> <input type="text" id="accountLastName" oninput="hideErrors('no-last-name')" /> <div id="no-last-name" class="error-container hidden"> <i class="google-material-icons">info</i> <span> <output>輸入姓氏</output> </span> </div> </div> </div> <div class="sign-in-buttons"> <div class="auth link"> <button type="button" onclick="signInStep('enterEmail')" class="button-link"> 回到上一步 </button> </div> <button type="button" class="auth blue" onclick="createAccount()"> 下一步 </button> </div> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a> </div> </form> </div> <div id="accountCreationConfirmation" class="box auth-box hidden"> <p> <div id="emailConfirmation" class="email-text"></div> 我們已向上方的電子郵箱發出確認信。請點擊信中的「確認」連結,確認你的帳戶。 </p> <p> 請檢查你的收件匣分頁或垃圾郵件。如果你沒有收到確認信,你可以點擊「重寄確認信」。 </p> <button class="auth blue" onclick="resendAccountConfirmation()"> 重寄確認信 </button> <button class="auth blue" onclick="accountCreationComplete()"> 完成 </button> <p id="confirmation-resent" class="hidden"> 確認信已重新寄出 </p> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a> </div> </div> <div id="resetPassword" class="box auth-box hidden"> <h1> 密碼重置 </h1> <p> 如果你忘記你的密碼,你可以要求重置密碼。我們會發給你一封含有重設密碼連結的信件,讓你重設密碼。 </p> <div class="sign-in-buttons"> <div class="auth link"> <button type="button" onclick="signInStep('enterPassword')" class="button-link"> 回到上一步 </button> </div> <button class="auth blue" onclick="resetPassword()"> 密碼重置 </button> </div> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a> </div> </div> <div id="postReset" class="box auth-box hidden"> <h1> 密碼重置 </h1> <p> 我們已經寄信到你的電子郵箱。請根據信中指示重新設定你的密碼。 </p> <div class="sign-in-buttons"> <div class="auth link"> <button type="button" onclick="signInStep('signinMethod')" class="button-link"> 回到上一步 </button> </div> </div> <div class="privacy-policy"> <a class="privacy-link" target="_blank" href="https://policies.google.com/privacy" > 隱私權政策 </a> </div> </div> </div> <div id="gated-signout" class="boxed-takeover"> <div class="box"> <h1> Forbidden </h1> <p> <output>Sorry, you do not have permission to access this resource.</output> </p> <button onclick="signOut()"> Sign out </button> </div> </div> <div id="user-upgrade-error" class="boxed-takeover"> <div class="box"> <h1>User account conflict</h1> <p> <output>Sorry, the user account you are using is now linked to Google. Please sign in with Google to use this account.</output> </p> <button onclick="signOut()"> 登出 </button> </div> </div> <div id="private-error" class="boxed-takeover"> <div class="box"> <div class="formatted-html"><h1>Forbidden</h1><p>You do not have permission to access this private event</p></div> <button onclick="signOut()"> Sign out </button> </div> </div> <div id="general-error" class="boxed-takeover"> <div class="box"> <h1>We&#39;ll be right back</h1> <p> We are having temporary difficulties, and are working to fix the issue. </p> </div> </div> <div id="cookie-error" class="boxed-takeover"> <div class="box"> <h1>Cookies are disabled</h1> <p> Cookies are required in order to sign in. Please enable cookies in your browser&#39;s settings and disable any adblockers. Then refresh this page. </p> </div> </div> <div id="auth-error" class="boxed-takeover"> <div class="box"> <h1>Error authenticating user</h1> <p> There was an error during authentication. Please refresh to try again. If this issue persists, please sign out and sign back in after reloading. </p> <button onclick="signOut()"> 登出 </button> </div> </div> <div id="offline-error" class="boxed-takeover"> <div class="box"> <h1>You&#39;re currently offline</h1> <p> Refresh the page when your connection is restored to return to the app. </p> </div> </div> <script defer src="/scripts/app.preload.97eb4396.js" ></script> <!-- Developer Profiles --> <script src="/static/scripts/developer_profiles_api_v0.2.3.js"></script> <script> window.templateBundleMap = { platform: { "default": { script: "/scripts/app.platform.default.js", style: "/styles/app.platform.default.css", }, "devfest": { script: "/scripts/app.platform.devfest.js", style: "/styles/app.platform.devfest.css", }, "cloud": { script: "/scripts/app.platform.cloud.04584a22.js", style: "/styles/app.platform.cloud.a9c1e38e.css", }, }, event: { "default": { script: "/scripts/app.event.default.77eb7c9f.js", style: "/styles/app.event.default.f4b51581.css", }, "cloud_2017": { script: "/scripts/app.event.cloud_2017.14fe68ec.js", style: "/styles/app.event.cloud_2017.978f9577.css", }, "cloud_2018": { script: "/scripts/app.event.cloud_2018.920955c7.js", style: "/styles/app.event.cloud_2018.4524a015.css", }, "cloud_summit_2018": { script: "/scripts/app.event.cloud_summit_2018.b80bb2df.js", style: "/styles/app.event.cloud_summit_2018.2828e67d.css", }, "cloud_transform_2018": { script: "/scripts/app.event.cloud_transform_2018.21a8e490.js", style: "/styles/app.event.cloud_transform_2018.fc10d7ff.css", }, "cloud_data_ai_2018": { script: "/scripts/app.event.cloud_data_ai_2018.502619fb.js", style: "/styles/app.event.cloud_data_ai_2018.66e30895.css", }, "devfest_2018": { script: "/scripts/app.event.devfest_2018.5614ac9a.js", style: "/styles/app.event.devfest_2018.55fd9704.css", }, "chrome_2018": { script: "/scripts/app.event.chrome_2018.cf503ed7.js", style: "/styles/app.event.chrome_2018.acf234a7.css", }, "cloud_q1_2019": { script: "/scripts/app.event.cloud_q1_2019.67fde800.js", style: "/styles/app.event.cloud_q1_2019.98f47d07.css", }, "global_events_gml_2019": { script: "/scripts/app.event.global_events_gml_2019.6695235b.js", style: "/styles/app.event.global_events_gml_2019.bb1763a3.css", }, "single_session": { script: "/scripts/app.event.single_session.6ddc3ca3.js", style: "/styles/app.event.single_session.d86eb8f4.css", }, }, theme: { gemini: "/styles/themes/gemini.f25f4bf0.css", youtube: "/styles/themes/youtube.6ad3b535.css", }, angularJsDependencies: "/scripts/dependencies.4f4b11f9.js" } </script> <div class="hidden" id="bad-browser"> <div id="bad-browser-shade"></div> <div id="bad-browser-text"> <span id="warning-icon" ><i class="google-material-icons">warning</i></span > <h2> Your browser<br /> is not supported </h2> <p> For the full experience, use Google Chrome, Firefox, Safari or Edge. </p> </div> </div> <script> // Show bad browser modal for IE and Opera browsers. Separated into // independent code block to prevent other script errors from blocking. // Internet Explorer 6-11 var isIE = !!document.documentMode; // Opera browser var isOpera = /(Opera|OPR\/)/g.test(window.navigator.userAgent); if (isIE || isOpera) { document.getElementById('bad-browser').className = ''; document.body.className += ' unsupported'; } </script> <script> const cookieBarScript = document.createElement('script') const lang = window.navigator.userLanguage || window.navigator.language || 'en'; cookieBarScript.setAttribute('data-glue-cookie-notification-bar-language', lang); cookieBarScript.setAttribute('src', 'https://www.gstatic.com/glue/cookienotificationbar/cookienotificationbar.min.js'); document.body.appendChild(cookieBarScript); </script> <script> function hideTempElements() { const elementIdsToHide = [ 'invalid-password', 'invalid-email', 'no-password', 'email-in-use', 'weak-password', 'create-account-no-password', 'no-first-name', 'no-last-name', 'login-retry-limit', 'confirmation-resent', ]; elementIdsToHide.forEach(id => { document.getElementById(id).classList.add('hidden'); }); } function signInStep(stepName) { hideTempElements(); const currentView = document.getElementById(stepName); document .getElementById('password-container') .classList.remove('hidden'); document.getElementById('password-sign-in').disabled = false; [ 'signinMethod', 'enterEmail', 'hasGoogleAccount', 'enterPassword', 'createAccount', 'accountCreationConfirmation', 'resetPassword', 'postReset', ] .filter(elementId => elementId !== stepName) .forEach(elementId => document.getElementById(elementId).classList.add('hidden') ); currentView.classList.remove('hidden'); const input = currentView.querySelector("input:not([disabled])"); if (input) { input.focus(); } } function checkEmail() { document.getElementById('invalid-email').classList.add('hidden'); const enteredEmail = document.getElementById('emailAddress').value; if (/^.*@google\.com$/i.test(enteredEmail)) { signInStep('hasGoogleAccount'); makeErrorAccessible(document.getElementById('hasGoogleAccount')); } else { const emailRegex = /.+@.+\..+/; if (!enteredEmail || !emailRegex.test(enteredEmail)) { document.getElementById('invalid-email').classList.remove('hidden'); makeErrorAccessible(document.getElementById('invalid-email')); return; } window.firebase .auth() .fetchSignInMethodsForEmail(enteredEmail) .then(signinOptions => { if (signinOptions.length === 0) { document.getElementById('accountEmail').value = enteredEmail; signInStep('createAccount'); } else if (signinOptions.includes('google.com')) { signInStep('hasGoogleAccount'); } else { document.getElementById( 'loginEmail' ).textContent = enteredEmail; signInStep('enterPassword'); } }) .catch(error => console.error(error)); } } function hideErrors(...errorIds) { for(let id of errorIds) { const errorToHide = document.getElementById(id); const errorMessage = errorToHide.querySelector("output"); if(!errorToHide.classList.contains("hidden")) { errorToHide.classList.add("hidden"); } errorMessage.removeAttribute("aria-role"); errorMessage.removeAttribute("aria-live"); } } function makeErrorAccessible(errorContainer) { const errorMessage = errorContainer.querySelector("output"); errorMessage.setAttribute("aria-role", "alert"); errorMessage.setAttribute("aria-live", "polite"); } function signInEmailPassword() { document.getElementById('invalid-password').classList.add('hidden'); document.getElementById('no-password').classList.add('hidden'); document.getElementById('password-sign-in').disabled = false; const password = document.getElementById('loginPassword').value; if (!password) { document.getElementById('no-password').classList.remove('hidden'); makeErrorAccessible(document.getElementById('no-password')); return; } window.firebase .auth() .signInWithEmailAndPassword( document.getElementById('loginEmail').textContent, document.getElementById('loginPassword').value ) .then(() => { window.location.reload(true); }) .catch(error => { if (error.code === 'auth/wrong-password') { document .getElementById('invalid-password') .classList.remove('hidden'); console.debug('wrong password'); makeErrorAccessible(document.getElementById('invalid-password')); } else if (error.code === 'auth/too-many-requests') { document .getElementById('password-container') .classList.add('hidden'); document .getElementById('login-retry-limit') .classList.remove('hidden'); makeErrorAccessible(document.getElementById('login-retry-limit')); document.getElementById('password-sign-in').disabled = true; } else { console.error(error); } }); } function createAccount() { hideTempElements(); const accountEmail = document.getElementById('accountEmail').value; const accountPassword = document .getElementById('accountPassword') .value.trim(); const accountFirstName = document .getElementById('accountFirstName') .value.trim(); const accountLastName = document .getElementById('accountLastName') .value.trim(); document.getElementById('accountPassword').value = accountPassword; document.getElementById('accountFirstName').value = accountFirstName; document.getElementById('accountLastName').value = accountLastName; if (!accountPassword) { document .getElementById('create-account-no-password') .classList.remove('hidden'); makeErrorAccessible(document.getElementById('create-account-no-password')); } if (!accountFirstName) { document.getElementById('no-first-name').classList.remove('hidden'); makeErrorAccessible(document.getElementById('no-first-name')); } if (!accountLastName) { document.getElementById('no-last-name').classList.remove('hidden'); makeErrorAccessible(document.getElementById('no-last-name')); } if (!accountPassword || !accountFirstName || !accountLastName) return; window.firebase .auth() .createUserWithEmailAndPassword(accountEmail, accountPassword) .then(resp => { resp.user.updateProfile({ displayName: `${accountFirstName} ${accountLastName}`, }).then(() => { // Solves issue with Firebase profile data propagation to the // user after creation–outlined here: // https://buganizer.corp.google.com/issues/204450136 const unsubscribe = window.firebase .auth() .onAuthStateChanged(user => { user.getIdToken(true); unsubscribe(); }); }); const emailConfirmation = document.getElementById("emailConfirmation"); if(emailConfirmation) { document.getElementById( 'emailConfirmation' ).textContent = accountEmail; } sendAccountConfirmation({ url: window.location.href }); signInStep('accountCreationConfirmation'); }) .catch(error => { if (error.code === 'auth/weak-password') { document .getElementById('weak-password') .classList.remove('hidden'); makeErrorAccessible(document.getElementById('weak-password')) } else if (error.code === 'auth/email-already-in-use') { document .getElementById('email-in-use') .classList.remove('hidden'); makeErrorAccessible(document.getElementById('email-in-use')) } else { console.error(error); } }); } function sendAccountConfirmation() { window.firebase.auth().currentUser.sendEmailVerification({ url: window.location.href }); } function resendAccountConfirmation() { window.firebase.auth().currentUser.sendEmailVerification({ url: window.location.href }); document .getElementById('confirmation-resent') .classList.remove('hidden'); } function accountCreationComplete() { location.reload(true); } function resetPassword() { const email = document.getElementById('loginEmail').textContent; window.firebase .auth() .sendPasswordResetEmail(email, { url: window.location.origin }) .then(() => { this.document.getElementById('email-text').textContent = email; this.signInStep('postReset'); }); } </script> </body> </html>