Hudson Taylor
Hudson Taylor

Reputation: 1162

Using jQuery Append

I am having trouble using jQuery's .append() method. Here's my code:

$('#all ul li').each(function() {
   if ($(this).children('.material-icons').hasClass('offline-icon') == false) {
      $('#online ul').append(this);
   }
});

$(document).ready(function() {
  // Declare all variables
  var users = ["freecodecamp", "trymacs", "phonecats"];
  var info = {};
  var i;
  var identifier;
  
  for (i = 0; i < users.length; i++) {
    $.getJSON("https://wind-bow.gomix.me/twitch-api/streams/" + users[i], function(json) {
      //create key for each object
      identifier = json["_links"].self;
      identifier = JSON.stringify(identifier);
      identifier = identifier.substr(identifier.lastIndexOf('/') + 1);
      identifier = identifier.slice(0, -1);
      
      // Add key/value pair to object
      info[identifier] = JSON.stringify(json);
      
      // Check if user is streaming using length of object
      if (info.freecodecamp.length < 400) {
        $('#freecodecamp .material-icons')
          .addClass('offline-icon')
          .html('portable_wifi_off');
      }
      if (info.trymacs.length < 400) {
        $('#trymacs .material-icons')
          .addClass('offline-icon')
          .html('portable_wifi_off');
      }
      if (info.phonecats.length < 400) {
        $('#phonecats .material-icons')
          .addClass('offline-icon')
          .html('portable_wifi_off');
      }
    });
  }
  
  // Filter content into online section
  $('#all ul li').each(function() {
    if ($(this).children('.material-icons').hasClass('offline-icon') == false) {
      $('#online ul').append(this);
    }
  });

  
  /*$.getJSON("", function(json) {

        // Only change code below this line.
        json = json.filter(function(val) {
          return (val.id !== 1);
        });
        
        
        // Only change code above this line.

        json.forEach(function(val) {

        });
  });
  
  // Thanks to Tyler Moeller for his help with this function
  /*users.map(function(val) {
    var url = 'https://wind-bow.gomix.me/twitch-api/streams/' + val
    $.getJSON(url, logTheData);
  });

  function logTheData(data) {
    status.push(data);
  }
  console.log(status)
});*/
});
body {
  background-color: pink;
}

#app {
  margin-top: 50px;
  padding: 0;
}

.head {
  background-color: #ee6e73;
  padding: 15px
}

.head h1 {
  margin: 0;
  font-size: 43px;
  color: #fff;
  text-shadow: 0.012em 0.012em #ccc;
}

.collection, .collection-item {
  border: none;
  border-bottom: none !important;
}
.collection-item img {
  height: 40px
}
.filter {
  background-color: #fff;
  padding: 0 !important;
}

.filter ul {
  margin: 0;
}

.filter ul li {
  border-top: 1px solid #eee;
}
img {
  border: 2px solid #ddd;
}
.offline-icon {
  color: #e53935;
}
<div class="row">
  <div class="col m8 offset-m2 s12 z-depth-1" id="app">
    <div class="head">
      <h1>Twitch.tv Streamers</h1>
    </div>
    <ul class="tabs">
      <li class="tab col s3"><a class="active" href="#all">All</a></li>
      <li class="tab col s3"><a href="#online">Online</a></li>
      <li class="tab col s3"><a href="#offline">Offline</a></li>
    </ul>
    <div id="all" class="col s12 filter">
      <ul class="collection">

        <li class="collection-item" id="freecodecamp">
            <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/freecodecamp-profile_image-d9514f2df0962329-300x300.png" alt="" class="circle">
            FreeCodeCamp
            <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <li class="collection-item" id="trymacs">
            <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/trymacs-profile_image-3c2ac4643bab750a-300x300.jpeg" alt="" class="circle">
            Trymacs
            <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <li class="collection-item" id="phonecats">
            <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/phonecats-profile_image-a536a337b2e58260-300x300.png" alt="" class="circle">
            phonecats
            <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
      <!--<li>Item <i class="material-icons">portable_wifi_off</i></li>
      <li>Item <i class="material-icons">wifi_tethering</i></li>
      <li>Item</li>-->
      </ul>
    </div>
    <div id="online" class="col s12 filter">
      <ul class="collection">
      
      </ul>
    </div>
    <div id="offline" class="col s12 filter">
      <ul>
        <li>Item</li>
        <li>Item</li>
        <li>Item</li>
      </ul>
    </div>
  </div>
</div>

Essentially, I only want list items without the offline-icon class to appear in the online tab. But, instead my code is moving all the items from the "all" tab to the "online" tab.

Thanks in advance for help.

Upvotes: 2

Views: 528

Answers (4)

Chiu
Chiu

Reputation: 374

Try to replace:

$('#online ul').append(this);

To

$('#online ul').append($(this).clone());

Upvotes: 1

Deep
Deep

Reputation: 9794

You need to display the option available in all tab as well as in the online tab if the class offline-icon is present.

1: Check for the class once the elements class is updated by the response of ajax call.

2: while checking for the class, add one additional check if the id of the li element is same as the identifier which will avoid causing same element to be appended twice.

$(document).ready(function() {
  // Declare all variables
  var users = ["freecodecamp", "trymacs", "phonecats"];
  var info = {};
  var i;
  var identifier;

  for (i = 0; i < users.length; i++) {
    $.getJSON("https://wind-bow.gomix.me/twitch-api/streams/" + users[i], function(json) {
      //create key for each object
      identifier = json["_links"].self;
      identifier = JSON.stringify(identifier);
      identifier = identifier.substr(identifier.lastIndexOf('/') + 1);
      identifier = identifier.slice(0, -1);

      // Add key/value pair to object
      info[identifier] = JSON.stringify(json);

      // Check if user is streaming using length of object
      if (info.freecodecamp && info.freecodecamp.length < 400) {
        $('#freecodecamp .material-icons')
          .addClass('offline-icon')
          .html('portable_wifi_off');
      }
      if (info.trymacs && info.trymacs.length < 400) {
        $('#trymacs .material-icons')
          .addClass('offline-icon')
          .html('portable_wifi_off');
      }
      if (info.phonecats && info.phonecats.length < 400) {
        $('#phonecats .material-icons')
          .addClass('offline-icon')
          .html('portable_wifi_off');
      }

      // Filter content into online section
      $('#all ul li').each(function() {

        if ($(this).attr("id") ==  identifier && $(this).children('.material-icons').hasClass('offline-icon')) {
          $('#online ul').append($(this).clone());
        }
        
      });


    });



  }





});
body {
  background-color: pink;
}
#app {
  margin-top: 50px;
  padding: 0;
}
.head {
  background-color: #ee6e73;
  padding: 15px
}
.head h1 {
  margin: 0;
  font-size: 43px;
  color: #fff;
  text-shadow: 0.012em 0.012em #ccc;
}
.collection,
.collection-item {
  border: none;
  border-bottom: none !important;
}
.collection-item img {
  height: 40px
}
.filter {
  background-color: #fff;
  padding: 0 !important;
}
.filter ul {
  margin: 0;
}
.filter ul li {
  border-top: 1px solid #eee;
}
img {
  border: 2px solid #ddd;
}
.offline-icon {
  color: #e53935;
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
<div class="row">
  <div class="col m8 offset-m2 s12 z-depth-1" id="app">
    <div class="head">
      <h1>Twitch.tv Streamers</h1>
    </div>
    <ul class="tabs">
      <li class="tab col s3"><a class="active" href="#all">All</a>
      </li>
      <li class="tab col s3"><a href="#online">Online</a>
      </li>
      <li class="tab col s3"><a href="#offline">Offline</a>
      </li>
    </ul>
    <div id="all" class="col s12 filter">
      <ul class="collection">

        <li class="collection-item" id="freecodecamp">
          <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/freecodecamp-profile_image-d9514f2df0962329-300x300.png" alt="" class="circle">FreeCodeCamp
          <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <li class="collection-item" id="trymacs">
          <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/trymacs-profile_image-3c2ac4643bab750a-300x300.jpeg" alt="" class="circle">Trymacs
          <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <li class="collection-item" id="phonecats">
          <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/phonecats-profile_image-a536a337b2e58260-300x300.png" alt="" class="circle">phonecats
          <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <!--<li>Item <i class="material-icons">portable_wifi_off</i></li>
      <li>Item <i class="material-icons">wifi_tethering</i></li>
      <li>Item</li>-->
      </ul>
    </div>
    <div id="online" class="col s12 filter">
      <ul class="collection">

      </ul>
    </div>
    <div id="offline" class="col s12 filter">
      <ul>
        <li>Item</li>
        <li>Item</li>
        <li>Item</li>
      </ul>
    </div>
  </div>
</div>

Upvotes: 0

SeinopSys
SeinopSys

Reputation: 8937

Your complete code is horribly inefficient. Despite the snippet you're showing being correct, you use an async $.getJSON call with a for loop, then inside the callback you check for every streamer by hand which will get tedious. Before the requests finish, no list item has the offline icon - that's only added after the request gives you a response, but by then your check already ran. See below for a fixed, more efficient solution:

$(document).ready(function() {
  // Declare all variables
  var users = ["freecodecamp", "trymacs", "phonecats"];
  var info = {};
  var i;
  var identifier;
  var finished = 0;
  var lastCheck = function() {
    // Filter content into online/offline sections
    $('#all ul li').each(function() {
      var isOffline = $(this).find('.offline-icon').length;
      $('#'+(isOffline?'offline':'online')+' ul').append($(this).clone());
    });
  };

  for (i = 0; i < users.length; i++) {
    (function(i) {
      var username = users[i];
      $.getJSON("https://wind-bow.gomix.me/twitch-api/streams/" + username, function(json) {
        //create key for each object
        identifier = json["_links"].self;
        identifier = JSON.stringify(identifier);
        identifier = identifier.substr(identifier.lastIndexOf('/') + 1);
        identifier = identifier.slice(0, -1);

        // Add key/value pair to object
        info[username] = JSON.stringify(json);

        if (info[username].length < 400) {
          $('#' + username + ' .material-icons')
            .addClass('offline-icon')
            .html('portable_wifi_off');
        }
      }).always(function() {
        if (++finished === users.length)
          lastCheck();
      });
    })(i);
  }
});
@import url('https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css');
@import url('http://fonts.googleapis.com/icon?family=Material+Icons');
 body {
  background-color: pink;
}
#app {
  margin-top: 50px;
  padding: 0;
}
.head {
  background-color: #ee6e73;
  padding: 15px
}
.head h1 {
  margin: 0;
  font-size: 43px;
  color: #fff;
  text-shadow: 0.012em 0.012em #ccc;
}
.collection,
.collection-item {
  border: none;
  border-bottom: none !important;
}
.collection-item > * {
  vertical-align: middle;
}
.collection-item img {
  height: 40px;
  margin-right: 5px;
}
.filter {
  background-color: #fff;
  padding: 0 !important;
}
.filter ul {
  margin: 0;
}
.filter ul li {
  border-top: 1px solid #eee;
}
img {
  border: 2px solid #ddd;
}
.offline-icon {
  color: #e53935;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js"></script>
<div class="row">
  <div class="col m8 offset-m2 s12 z-depth-1" id="app">
    <div class="head">
      <h1>Twitch.tv Streamers</h1>
    </div>
    <ul class="tabs">
      <li class="tab col s3"><a class="active" href="#all">All</a></li>
      <li class="tab col s3"><a href="#online">Online</a></li>
      <li class="tab col s3"><a href="#offline">Offline</a></li>
    </ul>
    <div id="all" class="col s12 filter">
      <ul class="collection">
        <li class="collection-item" id="freecodecamp">
          <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/freecodecamp-profile_image-d9514f2df0962329-300x300.png" alt="" class="circle">
          <span>FreeCodeCamp</span>
          <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <li class="collection-item" id="trymacs">
          <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/trymacs-profile_image-3c2ac4643bab750a-300x300.jpeg" alt="" class="circle">
          <span>Trymacs</span>
          <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <li class="collection-item" id="phonecats">
          <img src="https://static-cdn.jtvnw.net/jtv_user_pictures/phonecats-profile_image-a536a337b2e58260-300x300.png" alt="" class="circle">
          <span>phonecats</span>
          <i class="secondary-content material-icons">wifi_tethering</i>
        </li>
        <!--<li>Item <i class="material-icons">portable_wifi_off</i></li>
      <li>Item <i class="material-icons">wifi_tethering</i></li>
      <li>Item</li>-->
      </ul>
    </div>
    <div id="online" class="col s12 filter">
      <ul class="collection">

      </ul>
    </div>
    <div id="offline" class="col s12 filter">
      <ul class="collection">
		
      </ul>
    </div>
  </div>
</div>

Upvotes: 1

sinisake
sinisake

Reputation: 11318

I found problem:

http://codepen.io/anon/pen/qREqZg?editors=0110

Place your code inside get json function - under adding of classes, for example.

In the time when you have checked classes (doc ready/ajax call not finished), they aren't there, so now it should be fixed.

     if (info.phonecats.length < 400) {
        $('#phonecats .material-icons')
          .addClass('offline-icon')
          .html('portable_wifi_off');
      }
       $('#all ul li').each(function() {
    if ($(this).children('.material-icons').hasClass('offline-icon') == false) {
      $('#online ul').append($(this).clone());
    }
  });

EDIT: So, basically, since DOM is updated, after ajax request, wait for success, and rather add your snippet to, e.g. done() or always() callback: http://api.jquery.com/jquery.getjson/

Upvotes: 1

Related Questions