Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <!-- FCC Reviewers: please see comment on line 36 -->
<!-- UPDATE: If you're an FCC reviewer and have read the comment below, please feel free to visit the partially improved re-write which I have forked from this pen: https://codepen.io/no_stack_dub_sack/full/rLvVjG/ -->
<div class="container-fluid">
  <div id="statusSelectorWrapper">
    <h1 class="hidden-xs" style="padding-left: 50px; padding-top: 28px; padding-bottom: 20px;">TWITCH STREAMERS</h1>
    <div class="hidden-sm hidden-md hidden-lg" style="padding-left: 30px; padding-top: 30px; padding-bottom: 25px;">
      <div class="wrap">
        <h2>TWITCH&nbsp;</h2></div>
      <div class="wrap" style="width: 330px">
        <h2>STREAMERS</h2></div>
    </div>
    <div id="allButton" class="hide allowHover">
      <div class='circle1'></div>
    </div>
    <div id="allButton2">
      <div class="circle1"></div>
      <div id="navText0">ALL</div>
    </div>
    <div id="streamingButton" class="allowHover">
      <div class='circle2'></div>
    </div>
    <div id="boringButton" class="allowHover">
      <div class='circle3'></div>
    </div>
  </div>
  <div id="usersWrapper container-fluid">
    <div id="allUsers" class="show">
    </div>
    <div id="streamingUsers" class="hide">
    </div>
    <div id="boringUsers" class="hide">
    </div>
  </div>
  <div id="usersFooter"></div>
</div>
<!-- I know that for these challenges, we are supposed to put our own spin on the apps design wise, however, in this case, I felt that reverse engineering the app as closely as possible represented some unique challenges. For example, the animated buttons: these were a fun and difficult challenge that my own design likely wouldn't have included, and I thought it would be fun and useful to learn something more advanced like this. Although I'm reasonably sure that after 100 lines of code, there MUST be a better and more effecient way to do this. Which is another reason I chose this path: learning something completely on your own, and then having a good example to review after of the "right" way to do it, I think, is incredibly useful. After submitting this challenge, I intend to FINALLY take a peak at the example projects code, to be able to learn some places where I can improve this egregiously long bundle of code, to something smoother, more effecient, and easier to read. This has been a fun one though! And even though I'm sure there's plenty of places to improve, I'm pretty proud of myself and glad I was able to achieve my goal in creating a reasonably sound (at least on the outside!) and pretty close to exact replica of the original example. Check back at a later date for a fork of this project with new and improved code! -->
            
          
!
            
              /* {
  outline: 1px dotted black;
} */

html {
  overflow-y: scroll;
}

body {
  background: #B8B08D;
}

h2, h1 {
  font-family: 'Bowlby One', sans-serif;
  margin-top: 0;
  margin-bottom: 0;
  color: #2B303A;
}

.wrap {
  display: inline-block;
}

#statusSelectorWrapper {
  margin-bottom: 0px;
  margin-top: 15px;
  min-height: 90px;
  background: #0C7C59;
  position: relative;
}

#allButton, #streamingButton, #boringButton, #allButton2 {
  background: gray;
  border: 1px solid black;
  border-right: none;
  width: 25px;
  height: 20px;
  position: absolute;
  right: 0;
  cursor: pointer;
  padding-right: 5px;
  text-align: right;
  font-family: 'Bowlby One', sans-serif;
  font-size: 11px;
  color: #2B303A;
  padding-top: 3px;
}

#allButton, #allButton2 {
  top: 15px;
  width: 80px;
}

#streamingButton {
  top: 36px;
}

#boringButton {
  top: 57px;
}

#navText, #navText2, #navText3 {
  float: right;
}

.sliderWidth {
  width: 80px !important;
}

.circle1, .circle2, .circle3 {
  height: 12px;
  width: 12px;
  background: #0C7C59;
  float: left;
  margin-left: 5.5px;
  border-radius: 100px;
}

.circle2 {
  background: #D64933;
}

.circle3 {
  background: #2B303A;
}

.fader {
  display: none;
}

#allUsers, #streamingUsers, #boringUsers, #statusSelectorWrapper {
  max-width: 690px;
  margin-right: auto;
  margin-left: auto;
}

#allUsers {
  background: #ff9999;
}

#streamingUsers {
  background: #ff8080;
}

#boringUsers {
  background: #ff6666;
}

.stacked {
  text-align: center;
  height: 25px;
  padding-top: 4px;
}

.displayUserWrapper {
  padding-top: 10px;
  padding-bottom: 10px;
  border-top: 3px solid #B8B08D;
  font-weight: bold;
}

.displayUser {
  min-height: 50px;
  display: inline-block;
  position: relative;
  width: calc(100% - 60px);
}

.logo {
  margin-left: 10px;
  display: inline-block;
  height: 50px;
  border-radius: 50px;
  float: left;
}

.userName, .game {
  text-align: center;
  display: inline-block;
  height: 50px;
  padding-top: 16px;
}

p {
  width: auto;
  display: inline-block;
}

.game {
  width: 485px;
  font-style: italic;
}

.userName {
  width: 145px;
}

.onlineColor {
  background: #D64933;
}

.offlineColor {
  background: #2B303A;
  color: #B8B08D;
}

.offlineColor a {
   color: #D64933;
}

#usersFooter {
  max-width: 690px;
  height: 30px;
  margin-right: auto;
  margin-left: auto;
  margin-bottom: 20px;
  margin-top: 3px;
  background: #0C7C59;
}



            
          
!
            
                var twitch = "https://wind-bow.hyperdev.space/twitch-api/streams/";
  var users = ["ESL_SC2", "OgamingSC2", "cretetion", "FreeCodeCamp", "storbeck", "comster404", "HabathCX", "RobotCaleb", "noobs2ninjas", "TR7K", "sheevergaming", "brunofin", "Test_channel", "beohoff", "terakilobyte", "thomasballinger"];
  var api = "?callback=?";
  var userLogoMap = {
    ESL_SC2: "https://static-cdn.jtvnw.net/jtv_user_pictures/esl_sc2-profile_image-d6db9488cec97125-300x300.jpeg",
    FreeCodeCamp: "https://static-cdn.jtvnw.net/jtv_user_pictures/freecodecamp-profile_image-d9514f2df0962329-300x300.png",
    HabathCX: "https://static-cdn.jtvnw.net/jtv_user_pictures/habathcx-profile_image-d75385dbe4f42a66-300x300.jpeg",
    storbeck: "https://static-cdn.jtvnw.net/jtv_user_pictures/storbeck-profile_image-7ab13c2f781b601d-300x300.jpeg",
    OgamingSC2: "https://static-cdn.jtvnw.net/jtv_user_pictures/ogamingsc2-profile_image-9021dccf9399929e-300x300.jpeg",
    RobotCaleb: "https://static-cdn.jtvnw.net/jtv_user_pictures/robotcaleb-profile_image-9422645f2f0f093c-300x300.png",
    noobs2ninjas: "https://static-cdn.jtvnw.net/jtv_user_pictures/noobs2ninjas-profile_image-34707f847a73d934-300x300.png",
    cretetion: "https://static-cdn.jtvnw.net/jtv_user_pictures/cretetion-profile_image-12bae34d9765f222-300x300.jpeg",
    sheevergaming: "https://static-cdn.jtvnw.net/jtv_user_pictures/sheevergaming-profile_image-4e5d01c8ccb57beb-300x300.jpeg",
    TR7K: "https://static-cdn.jtvnw.net/jtv_user_pictures/tr7k-profile_image-814366faa230f65e-300x300.png",
    comster404: "http://www.madcapsoftware.com/images/icons/icon-captureLargeBg.png",
    brunofin: "http://www.madcapsoftware.com/images/icons/icon-captureLargeBg.png",
    beohoff: "http://www.madcapsoftware.com/images/icons/icon-captureLargeBg.png",
    terakilobyte: "http://www.madcapsoftware.com/images/icons/icon-captureLargeBg.png",
    thomasballinger: "http://www.madcapsoftware.com/images/icons/icon-captureLargeBg.png",
    Test_channel: "http://www.madcapsoftware.com/images/icons/icon-captureLargeBg.png"
  }

  for (var i = 0; i < users.length; i++) {
    $.getJSON(twitch + users[i] + api, function(data) {
      //console.log(data);  
      var deletedUser = "";
      if (data.status === 422) {
        deletedUser = data.message.split("'")[1];
        $("<div class='cc sorty'>" + "<div class='displayUserWrapper hidden-xs offlineColor'>" +  "<img class='logo' src='" + userLogoMap[deletedUser] + "' alt='logo'/>" + "<div class='displayUser'>" + "<div class='userName'>" + "<a href='https://www.twitch.tv/" +  deletedUser  + "' target='_blank'>" + deletedUser + "</a>" + "</div>" + "<div class='game'>Account Disabled</div>" + "</div>" + "</div>" + /* BEGIN HIDDEN DIVS */ "<div class='displayUserWrapper hidden-sm hidden-md hidden-lg offlineColor'>" + "<img class='logo' src='" + userLogoMap[deletedUser] + "' alt='logo'/>" + "<div class='displayUser'>" + "<div class='stacked'>" + "<a href='https://www.twitch.tv/" +  deletedUser  + "' target='_blank'>" + deletedUser + "</a>" + "</div>" + "<div class='stacked'>Account Disabled</div>" + "</div>" + "</div>" ).appendTo("#allUsers, #boringUsers");
      } else if (data.stream !== null) {
        var synopsis = data.stream.channel.status;
        var game = data.stream.channel.game;
        $("<div class='aa sorty'>" + "<div class='displayUserWrapper hidden-xs onlineColor'>" + "<img class='logo' src='" + data.stream.channel.logo + "' alt='logo'/>" + "<div class='displayUser'>" + "<div class='userName'>" + "<a href='" + data.stream.channel.url + "' target='_blank'>" + data.stream.channel.display_name + "</a>" + "</div>" + "<div class='game'>" + ifGameReturnsNull(game) + "<p> " + "&ndash; " + shortenLongDescriptions(synopsis) + "</p>" + "</div>" + "</div>" + "</div>" + /* BEGIN HIDDEN DIVS */ "<div class='displayUserWrapper hidden-sm hidden-md hidden-lg onlineColor'>" + "<img class='logo' src='" + data.stream.channel.logo + "' alt='logo'/>" + "<div class='displayUser'>" + "<div class='stacked'>" + "<a href='" + data.stream.channel.url + "' target='_blank'>" + data.stream.channel.display_name + "</a>" + "</div>" + "<div class='stacked'>" + ifGameReturnsNull(game) + "</div>" + "</div>" + "</div>" + "</div>").appendTo("#streamingUsers, #allUsers");
      } else if (data.stream === null) {
        var userLogoKey = data._links.self.slice(37);
        $("<div class='bb sorty'>" + "<div class='displayUserWrapper hidden-xs offlineColor'>" + "<img class='logo' src='" + userLogoMap[userLogoKey] + "' alt='logo'/>" + "<div class='displayUser'>" + "<div class='userName'>" + "<a href='https://www.twitch.tv/" +  userLogoKey  + "' target='_blank'>" + userLogoKey + "</a>" + "</div>" + "<div class='game'>Offline</div>" + "</div>" + "</div>" + /* BEGIN HIDDEN DIVS */ "<div class='displayUserWrapper hidden-sm hidden-md hidden-lg offlineColor'>" + "<img class='logo' src='" + userLogoMap[userLogoKey] + "' alt='logo'/>" + "<div class='displayUser'>" + "<div class='stacked'>" + "<a href='https://www.twitch.tv/" +  userLogoKey  + "' target='_blank'>" + userLogoKey + "</a>" + "</div>" + "<div class='stacked'>Offline</div>" + "</div>" + "</div>" + "</div>").appendTo("#boringUsers, #allUsers");;
      }
    }); // end getJSON
  } // end loop

 setTimeout(function(){
   var elem = $('#allUsers').find('.sorty').sort(sortMe);
   $('#allUsers').append(elem);
 }, 1000); 

function sortMe(b, a) {
     return a.className < b.className ? 1 : -1;
} 

function shortenLongDescriptions(str) {
  if (str.length > 50) {
    str = str.substr(0, 50) + "...";
  } else {
    str = str;
  }
  return str;
}

function ifGameReturnsNull(str) {
  if (str === null) {
    str = "Miscellaneous ";
  } else {
    str = str + " ";
  }
  return str;
}

// TOGGLE SCREENS:
var allUsers = $("#allUsers");
var streamingUsers = $("#streamingUsers");
var boringUsers = $("#boringUsers");

$("#streamingButton").click(function() {
  boringUsers.removeClass("show").addClass("hide");
  allUsers.removeClass("show").addClass("hide");
  streamingUsers.removeClass("hide").addClass("show");
});

$("#allButton").click(function() {
  streamingUsers.removeClass("show").addClass("hide");
  boringUsers.removeClass("show").addClass("hide");
  allUsers.removeClass("hide").addClass("show");
});

$("#boringButton").click(function() {
  allUsers.removeClass("show").addClass("hide");
  streamingUsers.removeClass("show").addClass("hide");
  boringUsers.removeClass("hide").addClass("show");
});

// NAV BUTTON ANIMATIONS:
// http://jsfiddle.net/8JHCe/8/
var allButton = $("#allButton");
var allButton2 = $("#allButton2");
var boringButton = $("#boringButton");
var streamingButton = $("#streamingButton");

streamingButton.bind("mouseenter", function(e) {
  if ($(this).hasClass("allowHover") === true) {
    $(this).animate({width: "80px"});
    $(".circle2").after("<div id='navText' class='fader'>ONLINE</div>");
    $("#navText").fadeIn("slow");
  }
})
streamingButton.bind("mouseleave", function(e) {
  if ($(this).hasClass("allowHover") === true) {
    $(this).animate({width: "25px"});
    $("#navText").fadeOut(150);
  }
})

streamingButton.click(function(e) {
  $(this).removeClass("allowHover").addClass("sliderWidth");
  allButton.removeClass("hide");
  allButton2.addClass("hide");
  allButton.animate({
    width: "25px"
  });
  allButton.removeClass("sliderWidth").addClass("allowHover");
  $("#navText2").fadeOut(150);
  boringButton.animate({
    width: "25px"
  });
  boringButton.removeClass("sliderWidth").addClass("allowHover");
  $("#navText3").fadeOut(150);
});

allButton.bind("mouseenter", function(e) {
  if ($(this).hasClass("allowHover") === true) {
    $(this).animate({width: "80px"});
    $(".circle1").after("<div id='navText2' class='fader'>ALL</div>");
    $("#navText2").fadeIn("slow")
  }
})
allButton.bind("mouseleave", function(e) {
  if ($(this).hasClass("allowHover") === true) {
    $(this).animate({width: "25px"})
    $("#navText2").fadeOut(150)
  }
})

allButton.click(function(e) {
  $(this).removeClass("allowHover").addClass("sliderWidth");
  streamingButton.animate({
    width: "25px"
  });
  streamingButton.removeClass("sliderWidth").addClass("allowHover");
  $("#navText").fadeOut(150);
  boringButton.animate({
    width: "25px"
  });
  boringButton.removeClass("sliderWidth").addClass("allowHover");
  $("#navText3").fadeOut(150);
});

boringButton.bind("mouseenter", function(e) {
  if ($(this).hasClass("allowHover") === true) {
    $(this).animate({width: "80px"});
    $(".circle3").after("<div id='navText3' class='fader'>OFFLINE</div>");
    $("#navText3").fadeIn("slow")
  }
})
boringButton.bind("mouseleave", function(e) {
  if ($(this).hasClass("allowHover") === true) {
    $(this).animate({width: "25px"})
    $("#navText3").fadeOut(150)
  }
})

boringButton.click(function(e) {
  $(this).removeClass("allowHover").addClass("sliderWidth");
  allButton.removeClass("hide");
  allButton2.addClass("hide");
  streamingButton.animate({
    width: "25px"
  });
  streamingButton.removeClass("sliderWidth").addClass("allowHover");
  $("#navText").fadeOut(150);
  allButton.animate({
    width: "25px"
  });
  allButton.removeClass("sliderWidth").addClass("allowHover");
  $("#navText2").fadeOut(150);
});
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console