0

I'm working on a project for freeCodeCamp and I'm running a for loop through an array of twitch.tv users. I've created a table and for each username in my array, it's supposed to add the new row, fill it with the data, and move onto the next element. The problem is that every time I run the code it seems to be choosing a random index in the array and running the loop through to equal the number of elements in the array. I think it's a display issue because it's connecting to the server for each individual call.

Hopefully someone can help me out.

var twitch = ['ESL_SC2', 'OgamingSC2', 'cretetion', 'freecodecamp', 'storbeck', 'habathcx', 'RobotCaleb', 'noobs2ninjas', 'ESL_LOL', 'wow_2', 'brunofin', 'comster404']

var streams = 'https://wind-bow.gomix.me/twitch-api/streams/';
var channels = 'https://wind-bow.gomix.me/twitch-api/channels/';
var users = 'https://wind-bow.gomix.me/twitch-api/users/';


var getStream = function(data) {

  if (data.stream === null) {
    $('.status').append('Offline');
  } else {
    var streamStatus = data.stream.channel.status;
    var html = '<td class="stream">' + streamStatus + '</td>';
    $('.stream').html(html);
  }

}
var getChannels = function(data) {
  var game = data.display_name;

  var logoHtml = data.logo;
  var channelUrl = data.url;
  var gameHtml = '<a href=' + channelUrl + ' target="_blank">' + game + '</a>';
  var logoHtml = '<img class="image" src="' + logoHtml + '">';
 
  $('.game').html(gameHtml);
  $('.logo').html(logoHtml);

}


$(document).ready(function() {

  $('.choice').on('click', function() {
    $('.choice').removeClass('selected');
    $(this).toggleClass('selected');
  });

  var table = $('<table id="twitch-table"></table>').appendTo('#content');

  for (var i = 0; i < twitch.length; i++) {
    var row = $('<tr></tr>').appendTo(table);
    $('<td class="logo"></td>').appendTo(row);
    $('<td class="game"></td>').appendTo(row);
    $('<td class="stream"></td>').appendTo(row);

    $.getJSON(streams + twitch[i], getStream, 'jsonp');
    $.getJSON(channels + twitch[i], getChannels, 'jsonp');



  }

});
body {
  padding: 0;
  margin: 0;
  font-family: 'Oswald', sans-serif;
  font-size: 100%;
}

a {
  text-decoration: none;
}

#main {
  width: 600px;
  margin: 2% auto 0;
}

#header {
  padding: 0;
  margin: 0;
  background: #116466;
  color: #d1e8e2;
  line-height: 100px;
  width: 100%;
}

h1 {
  margin: 0 0 0 5%;
  font-size: 300%;
}

#row {
  background: #285277;
  width: 100%;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  justify-content: space-between;
}

.choice {
  position: relative;
  text-align: center;
  width: 33%;
  background: #285277;
  padding: 5px 10px;
  display: inline-block;
  color: #d1e8e2;
  font-size: 150%;
}

.choice a {
  /*padding: 5px 20px;*/
  color: #d1e8e2;
}

#content {
  width: 100%;
  background: #efefef;
}


/*
.choice a:active {
 background: #1E3D59;
}
*/

.selected {
  background: #1E3D59;
}

.selected:after {
  content: '';
  position: absolute;
  top: 100%;
  right: 45%;
  width: 0;
  height: 0;
  border-top: solid 10px #1E3D59;
  border-left: solid 10px transparent;
  border-right: solid 10px transparent;
}

table {
  width: 600px;
}

tr {
  margin: 5px 0;
  display: flex;
  width: 100%;
  justify-content: space-between;
}

td {
  border-collapse: collapse;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
}

.game {
  padding-left: 10px;
  width: 100px;
  font-size: 120%;
  line-height: 75px;
  text-overflow: ellipsis;
}

.game a {
  color: #111;
}

.image {
  height: 75px;
  width: 75px;
}

.logo {
  padding: 3px 5px;
  box-sizing: border-box;
}

.stream {
  padding-right: 10px;
  width: 350px;
  display: inline-block;
  text-overflow: ellipsis;
  line-height: 75px;
}
<!DOCTYPE html>

<html>

<head>
  <title>Twitch.tv JSON API</title>
  <link href="https://fonts.googleapis.com/css?family=Oswald" rel="stylesheet">
  <script src="https://use.fontawesome.com/57c9bf8971.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>

<body>
  <div id='main'>
    <header id='header'>
      <h1>Twitch Streamers</h1>
    </header>
    <div id='row'>
      <ul>
        <li class='choice selected'><a href='#'>All</a></li>
        <li class='choice'><a href='#'>Online</a></li>
        <li class='choice'><a href='#'>Offline</a></li>
      </ul>
    </div>
    <div id='content'>

    </div>
  </div>
</body>

</html>
erikryanmoore
  • 387
  • 2
  • 7

3 Answers3

2

The problem is in these lines:

$('.game').html(gameHtml);
$('.logo').html(logoHtml);
$('.stream').html(html);

They select all lines with game class (or logo or stream) And change them all.

See here a fixed JSfiddle.

Shalom Peles
  • 1,413
  • 7
  • 16
  • That's exactly what I needed. Thank you. The only issue that I still have is that the first element in the array does not appear. Would you have a solution for that? – erikryanmoore Feb 19 '17 at 08:23
0

You need to use the callback function properly. Your getStreams and getChannels functions are applying data to all rows, instead of its own individual row.

Below are the modified callback functions declarations:

var getStream = function(url, idx) {
    $.getJSON(url, function(data){
        if (data.stream === null) {
            $('.status').append('Offline');
        } else {
            var streamStatus = data.stream.channel.status;
            var html = '<td class="stream">' + streamStatus + '</td>';
            $('tr').eq(idx).find('.stream').html(html);
        }
    });
}

var getChannels = function(url, idx) {
    $.getJSON(url, function(data){
        var game = data.display_name;
        var logoHtml = data.logo;
        var channelUrl = data.url;
        var gameHtml = '<a href=' + channelUrl + ' target="_blank">' + game + '</a>';
        var logoHtml = '<img class="image" src="' + logoHtml + '">';

        $('tr').eq(idx).find('.game').html(gameHtml);
        $('tr').eq(idx).find('.logo').html(logoHtml);
    });
}

And, call them within your for loop as:

getStream(streams + twitch[i], i);
getChannels(channels + twitch[i], i);

JSFiddle for your reference: https://jsfiddle.net/yogesh214/yxLu9mwg/4/

Yogesh Mistry
  • 1,556
  • 13
  • 18
0

I understand your problem now:

As @Shalom Peles said, you're using $('.stream') to select all the elements in the document with the class .stream instead of just the element within your row.

Instead use .find to select within an element. For example:

let row = $('<div class="my-row"></div>'); // creates a row
row.append(/* ... */);
let elementInsideRow = row.find('.my-column'); // this selects an element *inside* the row element.

Also: use let instead of var for all declarations


I edited your code to work for streams. Do the same for channels. Read the comments.

var twitch = ['ESL_SC2', 'OgamingSC2', 'cretetion', 'freecodecamp', 'storbeck', 'habathcx', 'RobotCaleb', 'noobs2ninjas', 'ESL_LOL', 'wow_2', 'brunofin', 'comster404']

var streams = 'https://wind-bow.gomix.me/twitch-api/streams/';
var channels = 'https://wind-bow.gomix.me/twitch-api/channels/';
var users = 'https://wind-bow.gomix.me/twitch-api/users/';

// refactor this like I did below
var getChannels = function(data) {
  var game = data.display_name;

  var logoHtml = data.logo;
  var channelUrl = data.url;
  var gameHtml = '<a href=' + channelUrl + ' target="_blank">' + game + '</a>';
  var logoHtml = '<img class="image" src="' + logoHtml + '">';
 
  $('.game').html(gameHtml);
  $('.logo').html(logoHtml);

}


$(document).ready(function() {

  $('.choice').on('click', function() {
    $('.choice').removeClass('selected');
    $(this).toggleClass('selected');
  });

  var table = $('<table id="twitch-table"></table>').appendTo('#content');

  // you need to use `let` here because you need block scope
  // in general, use `let` instead of `var` everywhere.
  // https://stackoverflow.com/questions/21906133/when-should-i-use-let-and-var
  for (let i = 0; i < twitch.length; i++) {
    let row = $('<tr></tr>');
    $.getJSON(streams + twitch[i], function(data) {
        
        $('<td class="logo"></td>').appendTo(row);
        $('<td class="game"></td>').appendTo(row);
        $('<td class="stream"></td>').appendTo(row);
        if (data.stream === null) {
            // instead of selecting all the elements with `.status`, use `find` to select *within* the `row` element
            // $('.status').append('Offline');
            row.find('.status').append('Offline');
        } else {
            var streamStatus = data.stream.channel.status;
            var html = '<td class="stream">' + streamStatus + '</td>';
            row.find('.stream').html(html);
        }
        // apend it when you're done
        row.appendTo(table);
    }, 'jsonp');

    // make the same changes for channel
    //$.getJSON(channels + twitch[i], getChannels, 'jsonp');



  }

});
body {
  padding: 0;
  margin: 0;
  font-family: 'Oswald', sans-serif;
  font-size: 100%;
}

a {
  text-decoration: none;
}

#main {
  width: 600px;
  margin: 2% auto 0;
}

#header {
  padding: 0;
  margin: 0;
  background: #116466;
  color: #d1e8e2;
  line-height: 100px;
  width: 100%;
}

h1 {
  margin: 0 0 0 5%;
  font-size: 300%;
}

#row {
  background: #285277;
  width: 100%;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  justify-content: space-between;
}

.choice {
  position: relative;
  text-align: center;
  width: 33%;
  background: #285277;
  padding: 5px 10px;
  display: inline-block;
  color: #d1e8e2;
  font-size: 150%;
}

.choice a {
  /*padding: 5px 20px;*/
  color: #d1e8e2;
}

#content {
  width: 100%;
  background: #efefef;
}


/*
.choice a:active {
 background: #1E3D59;
}
*/

.selected {
  background: #1E3D59;
}

.selected:after {
  content: '';
  position: absolute;
  top: 100%;
  right: 45%;
  width: 0;
  height: 0;
  border-top: solid 10px #1E3D59;
  border-left: solid 10px transparent;
  border-right: solid 10px transparent;
}

table {
  width: 600px;
}

tr {
  margin: 5px 0;
  display: flex;
  width: 100%;
  justify-content: space-between;
}

td {
  border-collapse: collapse;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
}

.game {
  padding-left: 10px;
  width: 100px;
  font-size: 120%;
  line-height: 75px;
  text-overflow: ellipsis;
}

.game a {
  color: #111;
}

.image {
  height: 75px;
  width: 75px;
}

.logo {
  padding: 3px 5px;
  box-sizing: border-box;
}

.stream {
  padding-right: 10px;
  width: 350px;
  display: inline-block;
  text-overflow: ellipsis;
  line-height: 75px;
}
<!DOCTYPE html>

<html>

<head>
  <title>Twitch.tv JSON API</title>
  <link href="https://fonts.googleapis.com/css?family=Oswald" rel="stylesheet">
  <script src="https://use.fontawesome.com/57c9bf8971.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>

<body>
  <div id='main'>
    <header id='header'>
      <h1>Twitch Streamers</h1>
    </header>
    <div id='row'>
      <ul>
        <li class='choice selected'><a href='#'>All</a></li>
        <li class='choice'><a href='#'>Online</a></li>
        <li class='choice'><a href='#'>Offline</a></li>
      </ul>
    </div>
    <div id='content'>

    </div>
  </div>
</body>

</html>
Community
  • 1
  • 1
Rico Kahler
  • 12,583
  • 9
  • 41
  • 63