Twitch Viewer

In this example below you will see how to do a Twitch Viewer with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by TranAP, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright TranAP ©
  • HTML
  • CSS
  • JavaScript
    <div id="container">
	<header>
		<h1>Twitch Streamers</h1>
	</header>
 <nav>
  <ul id="menu">
   <li id="all" class="active">All</li>
   <li id="online">Online</li>
   <li id="offline">Offline</li>
  </ul>
 </nav>
 <section id="channels">
 </section>
	
</div>
	
 <footer><small>Arden Tran</small></footer>

<template id="channelTemplate">
		<article class={{class}} data-url={{url}}>
				<h1>{{name}}</h1>
				<h2>{{status}}</h2>
				<p></small>{{description}}</small></p>
		</article>
	</template>

/*Downloaded from https://www.codeseek.co/TranAP/twitch-viewer-VWwjyx */
    $main: #279090;
$main-light: lighten($main, 10%);
$main-dark: darken($main, 10%);
$main-darkish: darken($main, 5%);
$secondary: #F0CC41;
$secondary-dark: darken($secondary, 10%);
$metal: grey;
$metal-dark: darken($metal, 10%);
$metal-light: lighten($metal, 10%);
$off-white: #FAFBFC;
$off-white-dark: darken($off-white, 2%);
$container-border-radius: 15px;

@mixin center {
	margin: auto;
	text-align: center;
}

body {
	background-color: $off-white;
}

footer {
	@include center;
}

#container {
	@include center;
	max-width: 600px;
	border: 10px solid $metal-dark;
	border-radius: $container-border-radius;
	//background: linear-gradient($metal, $metal-dark 50px, $metal-dark);
	background: linear-gradient(
		$metal,
		$metal-dark 30px,
		$metal-light 60px,
		$metal-dark 100px
	);
	//background: linear-gradient($metal, blue 30px, red 60px, green 100px, $metal-dark);
}

#menu {
	display: flex;
	justify-content: space-between;
	padding: 0;
	margin: 0;
	margin-bottom: 0;
	list-style-type: none;
	li {
		background-color: $main-dark;
		border-radius: $container-border-radius $container-border-radius 0 0;
		font-size: 1.3em;
		font-weight: bold;
		padding: 0.4em;
		width: 25%;
		&:hover {
			color: $secondary-dark;
			background-color: $main-darkish;
		}
	}
	.active {
		color: $secondary;
		background-color: $main;
	}
}

#channels {
	background-color: $metal;
	border-radius: 0 0 $container-border-radius $container-border-radius;
	.online {
		border-right: 6px solid $secondary-dark;
	}
	article {
		background-color: $main;
		&:last-child {
			border-radius: 0 0 $container-border-radius $container-border-radius;
		}
		border-right: 6px solid $main;
		display: flex;
		align-items: baseline;
		flex-wrap: wrap;
		h1 {
			flex: 1;
			font-size: 1.3em;
			text-align: left;
			padding-left: 30px;
			width: 50%;
		}
		h2 {
			flex: 1;
			font-size: 1.3em;
			text-align: right;
			padding-right: 30px;
			width: 50%;
		}
		p {
			width: 100%;
			margin: 0;
		}
		&:hover {
			background: linear-gradient($main-light, $main 20%, $main 80%, $main-light);
		}
	}
}



/*Downloaded from https://www.codeseek.co/TranAP/twitch-viewer-VWwjyx */
    "use strict";

// Dom Cache
const channels = document.getElementById("channels");
const templateInfo = document.getElementById("channelTemplate");
const allTab = document.getElementById("all");
const onTab = document.getElementById("online");
const offTab = document.getElementById("offline");

// Event Binding
allTab.addEventListener("click", changeView);
onTab.addEventListener("click", changeView);
offTab.addEventListener("click", changeView);
channels.addEventListener("click", openLink);

// Channel Array
const channelsList = [
	"ESL_SC2",
	"OgamingSC2",
	"cretetion",
	"freecodecamp",
	"storbeck",
	"habathcx",
	"RobotCaleb",
	"noobs2ninjas",
	"brunofin",
	"comster404"
];

// Template
const template = Handlebars.compile(templateInfo.innerHTML);

// Initialize
changeView();

// Turns each article into a link.
function openLink (event) {
		window.open(event.target.closest("article").getAttribute("data-url"), "_blank");
}


// Changes view
function changeView() {
	// Clears all channel lists
	channels.innerHTML = "";
	// Sets active tab if this is not undefined
	if (this) {
		const oldTab = this.parentNode.getElementsByClassName("active")[0];
		oldTab.classList.remove("active");
		this.classList.add("active");
	}
	// ID of button clicked, default to "all".
	let view = "all";
	if (this) {
		view = this.id;
	}
	// Renders each channel
	for (let channel of channelsList) {
		get("https://wind-bow.glitch.me/twitch-api/streams/" + channel, function(streamData) {checkOnline(streamData, channel, view)});
	}
}

function checkOnline(streamData, channel, view) {
	const cleanData = JSON.parse(streamData);
	let online = false;
	if (cleanData.stream) {
		online = true;
	}
	get("https://wind-bow.glitch.me/twitch-api/channels/" + channel, function(streamData) {checkReal(streamData, channel, view, online)});
}

// Twitch returns an error if channel never existed
function checkReal(data, channel, view, online) {
	const cleanData = JSON.parse(data);
	if (cleanData.hasOwnProperty("error") && view === "all") {
		channels.innerHTML += template({
			name: channel,
			status: "Not Found",
			url: cleanData.url
		});
	} else if (online && (view === "online" || view === "all")) {
		channels.innerHTML += template({
			name: channel,
			status: "Online",
			description: cleanData.status,
			url: cleanData.url,
			class: "online"
		});
	} else if (view === "offline" || view === "all") {
		channels.innerHTML += template({
			name: channel,
			status: "Offline",
			url: cleanData.url
		});
	}
}

// https://wind-bow.gomix.me/twitch-api does not work. Used .glitch.me instead.
function get(url, callback) {
	const xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
		if (this.readyState == 4 && this.status == 200) {
			if (callback) {
				callback(this.responseText);
			}
		}
	};
	xhr.open("GET", url, true);
	xhr.send();
}


Comments