How to _prevent_ divs from appearing in random order - javascript

Okay, so I'm learning front-end dev with javascript/jquery/bootstrap through FreeCodeCamp. This is not a core part of the project, but I don't understand it and it's distracting me too much. In this code pen here:
http://codepen.io/JDenman6/pen/zqeGwp/ --
I have an array of Twitch.tv usernames that I check through an API and build divs to display them based on the JSON object comes back from the API call.
The weird thing is that every time I refresh the page, I get the divs in a different (apparently random) order. I'm guessing that the API calls are going out asynchronously and the divs are appearing in the order that the API calls finish.
When I Googled for other people having problems with divs in random order I found many solutions for causing random display order, but nothing on preventing it. So then I went looking for a solution to sorting divs and found this post, Ordering DIVs based on class name using Javascript/Jquery, which led me to this bit of code:
$(function(){
var elem = $('#twitcherList').find('div').sort(sortMe);
$('#twitcherList').append(elem);
});
function sortMe(a, b) {
return a.className < b.className;
}
Only I haven't been able to get it to work. I forked off my original codepen to do some poking around here: http://codepen.io/JDenman6/pen/MeYOJP.
The list of divs in the twitcherList in the html tab is from inspecting the twitcherList after rendering the original code. I thought it might be easier to sort them if they're hard coded, rather than coming in from the API call. I also added a little test div and inserted some code into the sort function to 1) check that it was running and 2) double check that a.classname and b.classname were returning what I thought they were, which they are.
I feel like I'm missing something massive, fundamental, and possibly quite obvious. Any thoughts?

You need to return -1, 0 or 1 based on the condition for proper sorting.
function sortMe(a, b) {
return a.className.localeCompare(b.className);
}
For better browser support use,
function sortMe(a, b) {
return a.className < b.className ? 1 : -1;
}

Related

Trying to reduce redundancies

I wrote some code, but I am pretty sure, that this could be shorter but my brain just stopped working and therefore I want to ask you about some tipps.
The problem is, that there are kind of redundancies in the code and like I said, I am pretty sure, that some kind of loop or something could handle this problem.
This piece of code is, like the name of the function, for toggling two different contents. This is for simulating a header with two tabs and therefore to present different content, when one of the two tabs are clicked.
function toggleContent() {
if(!firstTab.classList.contains("active")) {
firstTab.classList.add("active");
secondTab.classList.remove("active");
firstContent.classList.add("visible");
secondContent.classList.remove("visible");
} else {
secondTab.classList.add("active");
firstTab.classList.remove("active");
secondContent.classList.add("visible");
firstContent.classList.remove("visible");
}
}
classList has a toggle method with a second argument that may help
function toggleContent() {
var isFirstTabActive = firstTab.classList.contains("active");
firstTab.classList.toggle("active", !isFirstTabActive);
secondTab.classList.toggle("active", isFirstTabActive);
firstContent.classList.toggle("visible", !isFirstTabActive);
secondContent.classList.toggle("visible", isFirstTabActive);
}
This doesn't take into consideration the possibility of even shorter code - however, as the HTML is a mystery, this will do

Javascript: Array not shifting, multiple setTimeout functions (JSON)

I'm really stuck on this javascript question!
So I'm making a web page that will be completely animated (so it can be used for display for example in a television). That animation will be configurable by the user (stored in a database).
Right now, I've already made the code to store the configuration and to get the configuration (I do an AJAX call and save the configuration in an array of json objects) and everything is as it should be.
The problem is in the animation in which I go through the array and use setTimeout function to create animations. To iterate through the array I rotate it
(I use array.push(array.shift()) according to the answer here).
The first time the intervalmaster function is used, everything goes according to plan, but when the function is called again I need to rotate the array once more (because of the last animation) and the array just doesn't rotate!
Bellow I've left a portion of the code that I'm using that reproduces the problem I'm getting. I've also added the array jsonanima with some possible values (In reality the array is probably much bigger and with higher values).
I really don't understand what is happening, I've also considered that this could be a problem of the multiple setTimeout functions because I've read somewhere (couldn't find the link, sorry!) that is not really advised to use multiple setTimeout.
If that's the case is there any other way to do this?
Thank you in advance!
EDIT: Thanks to the comment from mplungjan I've realized that if change the console.log(jsonanimate) to console.log(JSON.stringfy(jsonanima)) it outputs the correct values (the json array rotated). This got me even more confused! Why do I need to JSON.stringfy to get the array in the correct order?!
Anyway, can't test this with the full code now as I'm not in the office, tomorrow I'll give more feedback. Thank you mplungjan.
EDIT2: Finally solved my problem! So the thing was the call to the function recursivegroup (recursivegroup(0);), this call was made before I rotated the array, so when restarting the animation the array would still have the incorrect values and every sub-sequential value was wrong.
A special thanks to mplungjan and trincot for the comments that helped me debug this problem.
Bellow I leave the code corrected so anybody with the same problem can check it out.
jsonanima=[{"VD":5,"A":10,"diff":0.25},{"L":7,"IE":8,"diff":0.25}];
function intervalmaster(flag){
function recursivegroup(index)
{
if(index==0)
{
//animateeach(jsonanima,0);
}
setTimeout(function(){
//HERE IT WORKS
jsonanima.push(jsonanima.shift());
console.log(JSON.stringify(jsonanima));
//animateeach(jsonanima,0);
//removed the if statement, since it was irrelevant as mplungjan noted
recursivegroup(index+1);
},(jsonanima[0]['diff'])*60*1000);
}
//Changed this
//recursivegroup(0);
var mastertime=0;
for(var key in jsonanima)
{
mastertime+=(jsonanima[key]['diff']);
}
console.log(mastertime,flag);
console.log(JSON.stringify(jsonanima));
if(flag==true)
{
jsonanima.push(jsonanima.shift());
console.log(JSON.stringify(jsonanima));
}
//changed to here
recursivegroup(0);
masterinterval=setTimeout(function(){intervalmaster(true)},mastertime*60*1000);
}
intervalmaster(false);

Angular ngGrid Tree Control: Make a round trip on group expand

I am trying to use ngGrid to make somewhat of a "tree-control" which I can build dynamically by calling API's. ngGrid allows for grouping on rows, yet the nature of it requires that all rows be present at the beginning. This is unfortunate for the fact that an API to pull back all generation data for a File Integrity Monitoring system would be insanely slow and stupid. Instead, I wish to build the "tree" dynamically on the expansion of each generation.
I am trying to inject children (ngRows) into a group-row (ngAggregate) on a callback, yet I do not think that I am calling the correct constructor for the ngRows for the fact that the rows are ignored by the control
Through the use of the aggregateTemplate option on the gridOptions for ngGrid, I have been able to intersept the expansion of a group quite easily.
(maybe not easily, but still)
I've replaced the ng-click of the default template:
ng-click="row.toggleExpand()"
with:
ng-click="$parent.$parent.rowExpanded(row)"
I know that it's a bit of a hack, but we can get to that later. For now, it gets the job done.
The way that I discovered how to work my way up the $scope to my rowExpanded function was by setting a breakpoint in ngGrid's "row.toggleExpand" function and calling it from the template as so:
ng-click="row.toggleExpand(this)"
Once I retrieve the group I want, I call an API to get the children for said group. I then need to make the return as children of the row. I decided to do this by calling ngGrid's ngRow factory:
row.children = [];
for(var i = 0; i < childData.length; i++)
{
row.children[row.children.length] = row.rowFactory.buildEntityRow(childData[i], i);
}
row.toggleExpand();
... yet this does not appear to be working. The rows are not showing up after I do the expand! Why won't my rows show up?
Here's my current Plunker!
By the way
I've placed a debugger statement within the group-expand callback. As long as you have your debugger open, you should catch a breakpoint on the expansion of a group.
Thanks everybody!
I found my answer, I'm an idiot....
I got this control working, and then realized that it was a total hack, that I could have used the control the way it was meant to be used and it would have worked much better, had much better work-flow, and it would have saved me an entire day of development. If you are wondering how you use the control this way, the answer is that you don't.
I got the stupid thing to work by updating my data structure after the round trip and forcing the grid to refresh, pretty obvious. I had to set the grid options so that groups were always expanded and I had to control the collapser icon logic myself, outside of ngGrid. I never called row.toggleExpand. I also hid any rows with null values by a function call within an ng-if on my rowTemplate. After all that was said and done, I put my foot in my mouth.

snap.load() fails to load multiple svgs properly

Exactly how Snap.load() loads svgs internally. If run iteratively on array of svgs the script shows array index of bound. If run recursively the order of the images messes up. Although one by one loading works fine. Here is what i tried:
http://jsfiddle.net/nahid/C3q2r/
p.s: comment out the necessary portions to see the behavior.
I was originally thinking of another way (posted in google groups an answer), but I think this solution is a bit neater if it works for you, so putting this as an answer...
To get them in order, you could call the next loading on completion of the the previous loading, which is what I think you were trying to do.
jsfiddle here... http://jsfiddle.net/C3q2r/4/
var handlr = function( i ){
if(i >= svg_array.length) return;
var name = svg_array[i];
Snap.load(name,function(f){
var g = f.select('g');
footpaper[i].append(g.clone());
}, handlr( i + 1));
}
handlr(0);

Dual asynchronous loops, how to guarantee correct sorted order for end result? (javascript)

Before I start, please don't ask why I want to do this in javascript, just know that I need to and if it makes you feel any better, I simply want to.
So, say I've got an array with (this number is arbitrary, real applications would be in the 300's or more, however, I selected it because it's an odd number) 19 indexes in an array and I want to, for example, put those indexes into another array in the exact same order using two asynchronous loops to do it (I'm aware this can simply be done by doing arrayOne = arrayTwo; I'm just using arrays for this example.)
How could I guarantee the values being put into the second array are in the right order?
that is to say, what is the logic or general idea to do this? (code examples are also welcome, I am also at liberty to use jquery if need be.)
Stopping or halting to wait for one loop to be done would of course be counter intuitive to using asynchronous loops because they would be working at the same time to process this task faster.
Here is a JSfiddle that doesn't work in its current state but shows the basic concept of what I'm talking about (probably works if you take it out of jsfiddle and put it in a real .js file) I'm pretty sure this code shows how to construct the loops and a check for when both loops are complete but I have no idea how to make sure they are putting the variables in the right order.
I have more than likely not explained my self very well and I intend to revise and edit this question in a few hours if there are no responses. If you require any more details, please ask me in the comments and I will try to elaborate on what I mean. Thanks.
Well an obvious solution is to map the items in your original array into wrappers that store the original index,
then after everything is done, sort the result array according to the stored indices and unwrap the data.
arrayOne = ["#1", "#2", "#3", "#4", "#5", "#6", "#7", "#8", "#9", "#10", "#11", "#12", "#13", "#14", "#15", "#16", "#17", "#18", "#19"];
var wrapped = arrayOne.map( function(v, i){
return {
data: v,
index: i
}
});
...
if(loopOneDone && loopTwoDone){
//Unwrap
var unwrapped = arrayTwo.sort(function(a, b){
return a.index - b.index;
}).map( function(v) {
return v.data;
});
for (i=0;i<unwrapped.length;i++){
document.getElementById("p1").innerHTML= unwrapped[i] + "<br />" ;
}
console.log('All done!');
//Code ends here
}

Categories

Resources