2

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.

2
  • it looks like you are trying to append something that is already attached to something else Commented Jan 5, 2017 at 1:57
  • Please consider my solution, your current code will be a nightmare to expand if you decide to add more streamers. Commented Jan 5, 2017 at 2:49

4 Answers 4

1

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/

Sign up to request clarification or add additional context in comments.

1 Comment

Np, glad to help! :)
1

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>

Comments

1

Try to replace:

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

To

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

5 Comments

This seems to kind of work. But, my if statement doesn't seem to be doing anything. They just both end up having all items. Do you have any ideas?
Without cloning the DOM into two objects, you cannot make it appear on both list (all, online). If your implementation is sharing the same list, you can use DOM show() / hide() instead, not cloning the DOM.
got down vote with answer, even it is partial, so discouraging
@Chiu, yes, someone is nervous. I got downvotes even for answers which actually completely solves problems. We have to get used to it. ;) My upvote. ;)
I down-voted your answer precisely because it is partial; this alone will only solve one of at least two issues with the asker's code. There was also a lack of any explanation as to why this is needed - although that has since been provided as a comment to some degree by the looks of it, but at the very least it should be part of your answer. As it is right now this would have been a better fit for a comment instead.
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.