GW2 AP Calculator
by Perry Kaufman
HTML
<h1 class=gw2-form-title>
Guild Wars 2 Achievement Point Calculator
</h1>
<form id=gw2form class=gw2-form>
<div class=gw2-input-key-wrapper>
<input id=gw2key class=gw2-input-key name=key type=text maxlength=72 />
<label class=gw2-input-key-label for=gw2key>API Key</label>
</div>
<button id=gw2submit class=gw2-form-submit name=calc type=submit>
<label class=gw2-submit-label for=gw2submit >Calculate</label>
</button>
</form>
<div class=gw2-output-wrapper>
<label class=gw2-output-label for=gw2output>Achievement Points</label>
<output class=gw2-output id=gw2output form=gw2form name=total></output>
</div>
<p class=gw2-disclaimer>
<b>Disclaimer:</b>
Inaccurate due to some achievements not being included in the api.
</p>
CSS
@import url('https://fonts.googleapis.com/css?family=Raleway');
:root {
--gw2-red: rgb(170, 24, 23);
--gw2-darkred: rgb(62, 18, 9);
}
html {
box-sizing: border-box;
font-family: 'Raleway', sans-serif;
font-size: 18px;
}
body {
align-items: center;
display: flex;
flex-flow: column nowrap;
margin: 0;
min-width: 300px;
padding: 0;
}
b {
color: var(--gw2-red);
}
label {
font-weight: 600;
}
:invalid {
box-shadow: none;
}
* {
box-sizing: inherit;
}
.gw2-form-title {
color: var(--gw2-red);
font-size: 1.5em;
margin: 5px 10px;
}
.gw2-form {
align-items: center;
display: flex;
padding: 10px 5px;
max-width: 600px;
width: 100%;
}
/*Form Input*/
.gw2-input-key-wrapper {
font-size: 1rem;
height: 3em;
flex: 1;
position: relative;
}
.gw2-input-key {
border: 2px solid var(--gw2-red);
border-radius: 5px;
font-size: .8em;
height: 100%;
padding: 1.5em .5em 0 .5em;
width: 100%;
transition: all ease-in-out .25s;
}
.gw2-input-key:focus {
border-color: var(--gw2-darkred);
}
.gw2-input-key:invalid {
color: red;
}
.gw2-input-key-label {
color: var(--gw2-red);
font-size: .9rem;
font-weight: bold;
position: absolute;
top: 0.5em;
left: 0.7em;
}
/*Form Submit*/
.gw2-form-submit {
background: var(--gw2-red);
border: 2px solid transparent;
border-radius: 5px;
color: white;
font-size: 1rem;
font-weight: 600;
height: 3em;
margin-left: 5px;
padding: 0 0.5em;
position: relative;
transition: all ease-in-out .25s;
width: 6em;
}
.gw2-form-submit:disabled {
background: white !important;
border: 2px solid var(--gw2-red);
color: transparent;
}
.gw2-form-submit:disabled::before {
color: var(--gw2-red);
content: 'calculating...';
font-size: 0.6em;
left: 0;
position: absolute;
text-align: center;
top: 0.3em;
width: 100%;
}
@keyframes sidetoside {
25% {transform: translateX(-0.25em);}
75% {transform: translateX(0.25em);}
100% {transform:...
JavaScript
'use strict'
//Error thrown if a key is rejected by the API.
class KeyError extends Error {}
//Error thrown if an API fetch fails.
class FetchError extends Error {}
//A sample API key.
const KEY = 'C2E85010-36C2-D446-BA0D-1237A58B731C2504C928-7861-4928-AE47-F281AE27898C';
//The form...
const FORM = document.forms[0];
//The required length of an API key.
const KEY_LENGTH = 72;
/* Contains utilities for generating api urls.
*/
const GW2Util = {
_BASE_PATH: 'https://api.guildwars2.com',
_ACCOUNT_PATH: '/v2/account',
_ACHIEVE_PATH: '/v2/achievements',
_ACCOUNT_ACHIEVE_PATH: '/v2/account/achievements',
_TOKEN_INFO_PATH: '/v2/tokeninfo',
/* Returns API token info path.
*/
getTokenInfoPath(key) {
return this._BASE_PATH + this._TOKEN_INFO_PATH + '?access_token=' + key;
},
/* Returns API account info path.
*/
getAccountPath(key) {
return this._BASE_PATH + this._ACCOUNT_PATH + '?access_token=' + key;
},
/* Returns aPI Account achievements path
*/
getAccountAchievementPath(key) {
return this._BASE_PATH + this._ACCOUNT_ACHIEVE_PATH + '?access_token=' + key;
},
/* Returns API achievements path.
*/
getAchievementPath(ids) {
return this._BASE_PATH + this._ACHIEVE_PATH + '?ids=' + ids.join();
}
};
/* Async functions that can be used to access account
* and achievement information on the Guild Wars 2 API.
*/
const GW2API = {
/* Request options.
*/
_OPTIONS: {
method: 'GET',
mode: 'cors'
},
/* Gets data about the key from the API.
*/
async getTokenInfo(key) {
const request = new Request(GW2Util.getTokenInfo(key), this._OPTIONS);
let response;
try {
response = await fetch(request);
} catch(error) {
throw new FetchError('getTokenInfo(): GET request failed');
}
if (!response.ok) throw new KeyError('getTokenInfo(): ' + response.status);
return await response.json();
},
/* Get account data from the API.
*/
async getAccount(key) {
const request...