FreeCodeCamp Intermediate Exercise #4: Use the Twitch.tv JSON API

In this example below you will see how to do a FreeCodeCamp Intermediate Exercise #4: Use the Twitch.tv JSON API with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by webdevdaemon, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright webdevdaemon ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Twitch.tv API Widget</title>
  
  
  <link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css'>

      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <!-- MAIN -->
<div class="main page">
  <div class="header">
    <!-- TITLE -->
    <a target='_blank' href="https://twitch.tv">
			<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/479875/TWITCH-eyes%4064.png" class="img-responsive" alt="twitch.tv favicon logo" />
		</a>
    <div class="logo-wrap">
      <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/479875/Twitch%40192px.png" class="header-logo img-responsive" alt="twitch.tv blocktext logo" />
      <h2 class="title">
        fndr
      </h2>
    </div>
  </div>
  <ul class="list">
    <!-- populate LIST here -->
  </ul>
  <div class="nav">
    <div class="btn-group main-btns" role="group">
      <button type="button" class="btn btn-secondary btn-feat">
				<p class="nav-btn-text">Featured Streams</p>
			</button>
      <button type="button" class="btn btn-secondary btn-mid btn-fcc">
				<p class="nav-btn-text">FreeCodeCamp.com</p>
			</button>
    </div>
  </div>
</div>
<div class="modal-pos">
  <p>
    <span class="on-msg">FreeCodeCamp's 
      <span class="twitch-tv">
        twitch.tv
      </span>account
    <br />-is-
    </span>
    <span class="ok">STREAMING NOW!!!</span>
  </p>
  <div class="btn-wrapper">
    <a target='_blank' href="#" class="btn btn-success go-to go-to-link" id="go-to-twitch-fcc">
      VIEW STREAM
    </a>
    <a target='_blank' href="#" class="btn btn-default dismiss">
      DISMISS
    </a>
  </div>
</div>
<div class="modal-neg">
  <p class="">
    FreeCodeCamp is
    <br />
    <span class="grey">Currently UNAVAILABLE</span>
  </p>
  <div class="btn-wrapper">
    <a target='_blank' href="#" class="btn btn-default dismiss">DISMISS</a>
  </div>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.js'></script>

  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/webdevdaemon/freecodecamp-intermediate-exercise-4-use-the-twitchtv-json-api-aBdOWO */
@import url("https://fonts.googleapis.com/css?family=Bungee|Bungee+Shade|Aldrich|Exo 2:500,900");
html {
  box-sizing: border-box;
}

*, *::after, *::before {
  box-sizing: inherit;
}

body {
  background: #000;
  background-position: center center;
  font-size: 62.5%;
  min-height: 100vh;
}
@media screen and (min-width: 1025px) {
  body {
    background-size: contain;
    background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/479875/twitch-dark-logo-1600x900_shrink.jpg);
    background-repeat: no-repeat;
  }
}
@media screen and (min-width: 651px) and (max-width: 1024px) {
  body {
    background-size: contain;
    background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/479875/twitch-dark-logo-800x450_shrink.jpg);
    background-repeat: no-repeat;
  }
}
@media screen and (min-width: 320px) and (max-width: 650px) {
  body {
    background-size: contain;
    background-image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/479875/twitch-dark-logo-800x450_shrink.jpg");
    background-repeat: no-repeat;
  }
}

.main {
  background: #000;
  height: 100%;
  width: 100%;
}

.header {
  background: #6445a3;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 10vh;
  position: relative;
  padding: 0 3vmin;
  word-wrap: nowrap;
  z-index: 100;
  width: 100%;
}
.header .logo-wrap {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 33%;
}
.header .logo-wrap .header-logo {
  width: 20vmin;
  display: block;
  margin: 0;
}
.header .logo-wrap .title {
  padding: 0 0 0.33em 0;
  display: block;
  font-family: "Bungee Shade", "Aldrich", sans-serif;
  font-size: 4vmin;
  letter-spacing: -0.15rem;
  margin-left: 0 -0.5vmin 0 0;
  color: #fff;
}

.list {
  background: transparent !important;
  overflow: scroll;
  position: relative;
  height: 100%;
  max-height: 80vh;
  width: 100%;
  padding: 0;
  margin: 0;
  z-index: 80;
}
.list .list-item {
  align-items: center;
  background: #a995d2;
  border-radius: 1vmin;
  display: flex;
  flex-direction: row;
  height: 14vh;
  justify-content: space-between;
  margin: 0.5vh 2vw;
  overflow: hidden;
  padding: 0;
}
.list .list-item .featured-link-wrapper--logo {
  border: none;
  padding: 0;
  margin: 0;
  max-width: 25vw;
  height: 100%;
  width: 100%;
  background-repeat: no-repeat;
  background-size: cover;
  background-origin: border-box;
  background-position: 0 0;
}
.list .list-item .featured-link-wrapper--logo .featured-logo {
  border: none;
  height: 100%;
  margin: 0;
  padding: 0;
}
.list .list-item .featured-info-wrapper {
  display: flex;
  height: 100%;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-start;
  width: 70%;
}
.list .list-item .featured-info-wrapper .featured-link-wrapper--name {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  padding: 1vmin 0 0 0;
}
.list .list-item .featured-info-wrapper .featured-link-wrapper--name .featured-name {
  background-color: transparent !important;
  font-size: 3vh;
  font-family: "Aldrich", sans-serif;
  height: 5.5vh;
  text-decoration: underline;
  width: 100%;
  margin: 0;
  padding: 0;
}
.list .list-item .featured-info-wrapper .featured-link-wrapper--name .featured-viewers {
  font-size: 2vh;
  margin: 0;
  padding: 0;
}
.list .list-item .featured-info-wrapper .featured-link-wrapper--game {
  padding: 0 0 1vh 0;
}
.list .list-item .featured-info-wrapper .featured-link-wrapper--game .featured-game {
  cursor: pointer;
  display: block;
  font-size: 2.5vh;
  font-family: "Exo 2", sans-serif;
  font-style: italic;
  margin: 0;
}

.nav {
  width: 100vw;
  position: relative;
  z-index: 100;
  margin: 0;
  padding: 0;
}
.nav .main-btns {
  height: 10vh;
  border-radius: 10px 10px 0 0;
  width: 100%;
  background: #fff;
  position: fixed;
  bottom: 0;
}
.nav .main-btns .btn {
  background: #fff;
  color: #6445a3;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1vh 0 0 0;
  outline: none;
  height: 100%;
  width: 50%;
}
.nav .main-btns .btn .nav-btn-text {
  font-family: "Bungee", "Aldrich", sans-serif;
  font-size: 4vmin;
}

.modal-pos,
.modal-neg {
  background: #6f4eb4;
  border-radius: 5px;
  color: #fff;
  position: fixed;
  top: 33vh;
  left: 20vw;
  right: 20vw;
  padding: 2.5rem;
  text-align: center;
  width: 60vw;
  z-index: 1000;
}
.modal-pos p,
.modal-neg p {
  font-size: 5vmin;
  font-family: "Exo 2", sans-serif;
}

.btn-wrapper {
  display: flex;
  justify-content: space-between;
  border-radius: 12px;
  overflow: hidden;
}
.btn-wrapper a {
  height: 100%;
  width: 100%;
  font-family: "Bungee", "Aldrich", sans-serif;
  font-size: 3vmin;
  color: #6445a3 !important;
}
.btn-wrapper a:focus {
  outline: none !important;
}

.green {
  color: #00bb00;
}

.ok {
  color: white;
  border-radius: 10vw;
  font-family: "Bungee", "Aldrich", sans-serif;
  font-size: 4.5vmin;
  display: block;
  line-height: 1;
  text-align: center;
  width: 100%;
  margin: 0 auto;
  padding: 12px 8px;
}

.on-msg {
  font-weight: 500;
  display: block;
  font-family: "Exo 2", sans-serif;
  font-size: 5vmin;
  line-height: 1.2;
  margin: 3vmin aut0;
  width: 100%;
}

.twitch-tv {
  box-shadow: inset -1px 1px 0 #000;
  border-radius: 1vmin;
  display: inline-block;
  font-style: italic;
  font-weight: 900;
  background: #f2f1ef;
  padding: 0 2vmin 1vmin 1.5vmin;
  margin: 0 1vmin 0 auto;
  line-height: 1;
  color: #6445a3;
}

.go-to,
.dismiss {
  display: block;
  width: 50%;
}

.go-to-link {
  height: 100%;
  width: 100%;
}

.modal-pos {
  display: none;
}

.modal-neg {
  display: none;
}


/*Downloaded from https://www.codeseek.co/webdevdaemon/freecodecamp-intermediate-exercise-4-use-the-twitchtv-json-api-aBdOWO */
var cb = '?client_id=hq0ou3njtspttuf2ro5zmx8n7b8zkv0&callback=?';
// Googlify game title for title search on click
var searchQueryFromString = function searchQueryFromString(str) {
  return str.replace(/([.]|[,]|[&]|[?]|[ ])/gi, '+');
};
// stream JSON => HTML string
var streamHTML = function streamHTML(_ref) {
  var url = _ref.url,
      game = _ref.game,
      name = _ref.name,
      logo = _ref.logo,
      viewers = _ref.viewers;
  return '<li class=\'list-item\'>\n    <a class=\'featured-link-wrapper--logo\' href=\'' + url + '\'\n      style=\'background-image:url(' + logo + ');\' target=\'_blank\'></a>\n    <div class=\'featured-info-wrapper\'>\n    <a href=\'' + url + '\' class=\'featured-link-wrapper--name\'\n      target=\'_blank\'>\n    <p class=\'featured-name\'>' + name + '</p>\n    <p class=\'featured-viewers\'>' + viewers + ' watching</p></a>\n    <a target=\'_blank\' class=\'featured-link-wrapper--game\' \n      href=\'http://google.com/search?q=' + searchQueryFromString(game) + '\'>\n    <p class=\'featured-game\'>' + game + '</p>\n    </a></div>\n  </li>';
};

$(document).ready(function () {
  var $f_list = $('.list'); // feature-list element
  var streamListInit = function streamListInit() {
    return $f_list.html('');
  }; // clear contents

  /*
    ////// GET & RENDER FEATURED STREAMS LIST //////|>
  */var getFeatured = function getFeatured() {
    var urlFeat = 'https://wind-bow.glitch.me/twitch-api/streams/featured' + cb;
    $.ajax({
      dataType: 'json',
      url: urlFeat,
      method: 'GET',
      data: 'application/json-p',
      success: function success(_ref2) {
        var featured = _ref2.featured;

        var obj = {};
        featured.forEach(function (item, index, array) {
          var ch = item.stream.channel;
          obj.viewers = item.stream.viewers;
          obj.url = ch.url;
          obj.game = ch.game;
          obj.name = ch.display_name;
          obj.logo = ch.logo;
          $f_list.append($(streamHTML(obj)));
        });
      }
    });
  };

  /*
    ////// CHECK FOR FCC STREAM, IF ON => DO STUFF //////|>
  */var getFccStream = function getFccStream() {
    var urlFcc = 'https://wind-bow.glitch.me/' + 'freecodecamp' + cb;
    $.ajax({
      dataType: 'json',
      url: urlFcc,
      method: 'GET',
      data: 'application/json-p',
      success: function success(r) {
        console.log(r.stream);
        if (r.stream !== null) {
          $('.go-to-link').attr('href', 'https://twitch.tv/freecodecamp');
          $('.modal-pos').fadeIn(300);
        } else {
          $('.go-to-link').attr('href', 'https://twitch.tv/freecodecamp');
          $('.modal-neg').fadeIn(300);
        }
      }
    });
  };

  /*
    ////// EVENT LISTENERS & HANDLERS //////|>
  */var hideModal = function hideModal() {
    $('.modal-neg').hide();
    $('.modal-pos').hide();
  };
  // featured streams btn
  $('.btn-feat').click(function () {
    hideModal();
    if (!$f_list.children('li')[0]) {
      getFeatured();
    } else {
      streamListInit();
    }
  });
  // FCC.com Stream btn
  $('.btn-fcc').click(function () {
    return getFccStream();
  });
  // Modal Dismiss btn
  $('.dismiss').click(hideModal);
  // Close Modal on Outer Click
  $('body').click(function (evt) {
    return evt.currentTarget !== $('.modal-pos').get(0) && hideModal();
  });
});

Comments