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.
-
it looks like you are trying to append something that is already attached to something elseBindrid– Bindrid2017年01月05日 01:57:45 +00:00Commented 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.SeinopSys– SeinopSys2017年01月05日 02:49:06 +00:00Commented Jan 5, 2017 at 2:49
4 Answers 4
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/
1 Comment
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
Try to replace:
$('#online ul').append(this);
To
$('#online ul').append($(this).clone());
5 Comments
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>