Skip to content

Instantly share code, notes, and snippets.

@Decicus
Last active December 9, 2019 11:11
Show Gist options
  • Save Decicus/03d8c3b9e576febd96e0f64cdf64d8d6 to your computer and use it in GitHub Desktop.
Save Decicus/03d8c3b9e576febd96e0f64cdf64d8d6 to your computer and use it in GitHub Desktop.
Very basic progress bar / goal example with Twitch subpoints - Licensed under MIT License
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cosmo/bootstrap.min.css" rel="stylesheet" integrity="sha384-qdQEsAI45WFCO5QwXBelBe1rR9Nwiss4rGEqiszC+9olH1ScrLrMQr1KmDR964uZ" crossorigin="anonymous">
<style type="text/css">
body {
margin-top: 40px;
}
</style>
<script type="text/javascript">
const params = new URLSearchParams(window.location.search);
/**
* The channel that should be used in the subpoints API.
*/
const channel = params.get('channel') || 'decicus';
/**
* The "goal" of how many subpoints you want
*/
const goal = parseInt(params.get('goal'), 10) || 25;
/**
* How many subpoints to subtract from the final count.
*
* This is ignored when `useTestValues` is true,
* because it generates random numbers anyways.
*/
const subtract = parseInt(params.get('subtract'), 10) || 0;
/**
* Default: `true` = It displays: "5.55%" instead
*
* `false` = It displays: "subpoints / goal" - Example: 555 / 100000
*/
const percentageText = params.get('percentage_text') === '0' ? false : true;
/**
* Specify the height of the progress bar.
*
* Default is 20 (px)
*/
const height = params.get('height') || '20';
/**
* How often the subpoints should be updated.
*/
const intervalSeconds = 60;
/**
* Default: `false` - Normal behavior. Regularly requests a new subpoints from the API and updates values accordingly.
*
* `true` - Instead of using the API, it will generate a random number between 0 and `goal`
* and use that value in progress bar.
* Mainly used for debugging / testing purposes
*/
const useTestValues = params.get('test') === '1';
</script>
</head>
<body>
<div class="container-fluid">
<div id="progress-parent" class="progress mx-auto" style="height: 0px;">
<div id="bar" class="progress-bar bg-success" style="width: 0%;"></div>
</div>
</div>
<script type="text/javascript">
const bar = document.getElementById('bar');
const progressParent = document.getElementById('progress-parent');
/**
* Logging mainly used for debugging
*/
function log(funcName, text)
{
// Only log when using test values
if (!useTestValues)
{
return;
}
const validTypes = ['string', 'number'];
console.log(`[${funcName}] ${text}`);
// Log objects and such separately.
if (!validTypes.includes(typeof text)) {
console.log(text);
}
}
/**
* Contacts the API to retrieve the current subpoints.
*/
async function getSubpoints()
{
const response = await fetch(`https://decapi.me/twitch/subpoints/${channel}?subtract=${subtract}`);
const subpoints = await response.text();
/**
* Verify that the response is only digits. Error responses should be ignored
*/
if (/^\d+$/.test(subpoints)) {
log('getSubpoints', subpoints);
return parseInt(subpoints, 10);
}
log('getSubpoints', 'null');
return null;
}
/**
* Updates the progress bar with the correct visuals.
*/
async function setProgressBar(subpoints)
{
const ratio = subpoints / goal;
const percentage = `${(ratio * 100).toFixed(2)}%`;
const ratioText = `${subpoints} / ${goal}`;
log('setProgressBar', percentage);
log('setProgressBar', ratioText);
bar.style.width = percentage;
bar.innerText = percentageText ? percentage : ratioText;
progressParent.style.height = `${height}px`;
}
/**
* Used for testing.
* Generates a random "subpoints" value to see how the progress bar behaves.
*/
async function testRandomSubpoints()
{
return Math.floor(Math.random() * goal) + 1;
}
/**
* Helper function for updating subpoints
* This checks if we should use test values or not.
*/
async function updateSubpoints()
{
let subpoints = null;
if (useTestValues)
{
subpoints = await testRandomSubpoints();
}
else
{
subpoints = await getSubpoints();
}
log('updateSubpoints', subpoints);
if (Number.isInteger(subpoints))
{
setProgressBar(subpoints);
}
}
document.addEventListener('DOMContentLoaded', async() => {
await updateSubpoints();
setInterval(async() => {
await updateSubpoints();
}, intervalSeconds * 1000);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment