HeliosLauncher/app/login.ejs
Daniel Scalzi ec9e95c130
Working on binding each view together.
Separate views are stored in an ejs file. When the app starts, each file will be loaded, with the DOM elements hidden. Based on the state of the application, a specific view will be fadded in. Switching between views will use this principle.

Moved contents of index.ejs to landing.ejs to make it compatible with the new format. As a result, index.ejs is deprecated and will be removed once it is no longer needed for reference.
2018-04-02 16:05:48 -04:00

267 lines
12 KiB
Plaintext

<div id="loginContainer" style="display: none;">
<div id="loginContent">
<div id='loginForm'>
<img id="loginImageSeal" src="assets/images/WesterosSealCircle.png"/>
<span class="loginSpan" id="loginSubheader">MEMBER LOGIN</span>
<div class="loginFieldContainer">
<svg id="profileSVG" class="loginSVG" viewBox="40 37 65.36 61.43">
<g>
<path d="M86.77,58.12A13.79,13.79,0,1,0,73,71.91,13.79,13.79,0,0,0,86.77,58.12M97,103.67a3.41,3.41,0,0,0,3.39-3.84,27.57,27.57,0,0,0-54.61,0,3.41,3.41,0,0,0,3.39,3.84Z"/>
</g>
</svg>
<span class="loginErrorSpan" id="loginEmailError">* Invalid Value</span>
<input id="loginUsername" class="loginField" type="text" placeholder="EMAIL"/>
</div>
<div class="loginFieldContainer">
<svg id="lockSVG" class="loginSVG" viewBox="40 32 60.36 70.43">
<g>
<path d="M86.16,54a16.38,16.38,0,1,0-32,0H44V102.7H96V54Zm-25.9-3.39a9.89,9.89,0,1,1,19.77,0A9.78,9.78,0,0,1,79.39,54H60.89A9.78,9.78,0,0,1,60.26,50.59ZM70,96.2a6.5,6.5,0,0,1-6.5-6.5,6.39,6.39,0,0,1,3.1-5.4V67h6.5V84.11a6.42,6.42,0,0,1,3.39,5.6A6.5,6.5,0,0,1,70,96.2Z"/>
</g>
</svg>
<span class="loginErrorSpan" id="loginPasswordError">* Required</span>
<input id="loginPassword" class="loginField" type="password" placeholder="PASSWORD"/>
</div>
<div id="loginOptions">
<span class="loginSpanDim">
<a href="https://help.mojang.com/customer/en/portal/articles/329524-change-or-forgot-password">forgot password?</a>
</span>
<label id="checkmarkContainer">
<input id="loginRememberOption" type="checkbox" checked>
<span id="loginRememberText" class="loginSpanDim">remember me?</span>
<span class="loginCheckmark"></span>
</label>
</div>
<button id="loginButton" disabled>
<div id="loginButtonContent">
LOGIN
<svg id="loginSVG" viewBox="0 0 24.87 13.97">
<defs>
<style>.arrowLine{fill:none;stroke:#FFF;stroke-width:2px;transition: 0.25s ease;}</style>
</defs>
<polyline class="arrowLine" points="0.71 13.26 12.56 1.41 24.16 13.02"/>
</svg>
<div class="circle-loader">
<div class="checkmark draw"></div>
</div>
<!--<div class="spinningCircle" id="loginSpinner"></div>-->
</div>
</button>
<div id="loginDisclaimer">
<span class="loginSpanDim" id="loginRegisterSpan">
<a href="https://minecraft.net/en-us/store/minecraft/">Need an Account?</a>
</span>
<p class="loginDisclaimerText">Your password is sent directly to mojang and never stored.</p>
<p class="loginDisclaimerText">WesterosCraft is not affiliated with Mojang AB.</p>
</div>
</div>
</div>
<div id="loginErrorContainer">
<div id="loginErrorContent">
<span id="loginErrorTitle">LOGIN FAILED:<br>INVALID CREDENTIALS</span>
<span id="loginErrorDesc">Either the email or password you supplied is invalid. Please ensure everything is correct and try again.</span>
<button id="loginErrorAcknowledge">Try Again</button>
</div>
</div>
<script type="application/javascript">
//const validEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i
// Validation Regexes.
const validUsername = /^[a-zA-Z0-9_]{1,16}$/
const basicEmail = /^\S+@\S+\.\S+$/
// DOM cache.
const loginContainer = document.getElementById('loginContainer')
const loginErrorTitle = document.getElementById('loginErrorTitle')
const loginErrorDesc = document.getElementById('loginErrorDesc')
const loginErrorAcknowledge = document.getElementById('loginErrorAcknowledge')
const loginEmailError = document.getElementById('loginEmailError')
const loginUsername = document.getElementById('loginUsername')
const loginPasswordError = document.getElementById('loginPasswordError')
const loginPassword = document.getElementById('loginPassword')
const checkmarkContainer = document.getElementById('checkmarkContainer')
const loginRememberOption = document.getElementById('loginRememberOption')
const loginButton = document.getElementById('loginButton')
// Control variables.
let lu = false, lp = false
// Show error element.
function showError(element, value){
element.innerHTML = value
element.style.opacity = 1
}
// Shake error element.
function shakeError(element){
if(element.style.opacity == 1){
element.classList.remove('shake')
void element.offsetWidth
element.classList.add('shake')
}
}
// Validate email field is neither empty nor invalid.
function validateEmail(value){
if(value){
if(!basicEmail.test(value) && !validUsername.test(value)){
showError(loginEmailError, '* Invalid Value')
loginDisabled(true)
lu = false
} else {
loginEmailError.style.opacity = 0
lu = true
if(lp){
loginDisabled(false)
}
}
} else {
lu = false
showError(loginEmailError, '* Required')
loginDisabled(true)
}
}
// Validate password field is not empty.
function validatePassword(value){
if(value){
loginPasswordError.style.opacity = 0
lp = true
if(lu){
loginDisabled(false)
}
} else {
lp = false
showError(loginPasswordError, '* Required')
loginDisabled(true)
}
}
// Emphasize errors with shake when focus is lost.
loginUsername.addEventListener('focusout', (e) => {
validateEmail(e.target.value)
shakeError(loginEmailError)
})
loginPassword.addEventListener('focusout', (e) => {
validatePassword(e.target.value)
shakeError(loginPasswordError)
})
// Validate input for each field.
loginUsername.addEventListener('input', (e) => {
validateEmail(e.target.value)
})
loginPassword.addEventListener('input', (e) => {
validatePassword(e.target.value)
})
// Enable or disable login button.
function loginDisabled(v){
if(loginButton.disabled !== v){
loginButton.disabled = v
}
}
// Enable or disable loading elements.
function loginLoading(v){
if(v){
loginButton.setAttribute('loading', v)
loginButton.innerHTML = loginButton.innerHTML.replace('LOGIN', 'LOGGING IN')
} else {
loginButton.removeAttribute('loading')
loginButton.innerHTML = loginButton.innerHTML.replace('LOGGING IN', 'LOGIN')
}
}
// Disable or enable login form.
function formDisabled(v){
loginDisabled(v)
loginUsername.disabled = v
loginPassword.disabled = v
if(v){
checkmarkContainer.setAttribute('disabled', v)
} else {
checkmarkContainer.removeAttribute('disabled')
}
loginRememberOption.disabled = v
}
function resolveError(err){
if(err.cause != null && err.cause === 'UserMigratedException') {
return {
title: 'Error During Login:<br>Invalid Credentials',
desc: 'You\'ve attempted to login with a migrated account. Try again using the account email as the username.'
}
} else {
if(err.error != null){
if(err.error === 'ForbiddenOperationException'){
if(err.errorMessage != null){
if(err.errorMessage === 'Invalid credentials. Invalid username or password.'){
return {
title: 'Error During Login:<br>Invalid Credentials',
desc: 'The email or password you\'ve entered is incorrect. Please try again.'
}
} else if(err.errorMessage === 'Invalid credentials.'){
return {
title: 'Error During Login:<br>Too Many Attempts',
desc: 'There have been too many login attempts with this account recently. Please try again later.'
}
}
}
}
}
}
return {
title: err.error,
desc: err.errorMessage
}
}
loginButton.addEventListener('click', () => {
// Disable form.
formDisabled(true)
// Show loading stuff.
loginLoading(true)
AuthManager.addAccount(loginUsername.value, loginPassword.value).then((value) => {
loginButton.innerHTML = loginButton.innerHTML.replace('LOGGING IN', 'SUCCESS')
$('.circle-loader').toggleClass('load-complete')
$('.checkmark').toggle()
console.log(value)
}).catch((err) => {
loginLoading(false)
$('#loginErrorContainer').css('display', 'flex').hide().fadeIn(250)
loginContainer.setAttribute('error', true)
const errF = resolveError(err)
loginErrorTitle.innerHTML = errF.title
loginErrorDesc.innerHTML = errF.desc
console.log(err)
})
// Temp for debugging, use procedure with real code.
setTimeout(() => {
loginButton.innerHTML = loginButton.innerHTML.replace('LOGGING IN', 'SUCCESS')
$('.circle-loader').toggleClass('load-complete')
$('.checkmark').toggle()
}, 2500)
})
loginErrorAcknowledge.addEventListener('click', () => {
formDisabled(false)
loginContainer.removeAttribute('error', false)
$('#loginErrorContainer').fadeOut(250)
})
</script>
<!-- Will reuse this down the line, then it will be removed from this file. -->
<!--<div id="loginLoading">
<div id="loginLoadingContent">
<div id="loadSpinnerContainer">
<img id="loadCenterImage" src="assets/images/westeroscraftlogo1.png">
<img id="loadSpinnerImage" class="rotating" src="assets/images/westeroscraftlogo2.png">
</div>
<span id="loadDescText">LOGGING IN</span>
</div>
</div>-->
</div>