Reputation: 1162
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
Reputation: 374
Try to replace:
$('#online ul').append(this);
To
$('#online ul').append($(this).clone());
Upvotes: 1
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
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
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