I'll let you see first what i got:
CODE
I decided to experiment and make a script which order numbers in an array in every possible way.
The first way I'm doing is the "Selection mode", where you find the lower value of the array and you put it at the first position. As you can see I printed it into a table to make it funnier, but here comes my question, i want to put a delay at the end of every loop, where i highlight the values that I'm going to exchange, but for some reason it just organize all the table and then render it instead of going step by step.
Now I'm going to proceed to explain a bit my code ^^u:
If you click at "Restart" you'll get a new bunch of random numbers, and if you click at "Selection" the array will become ordered.
Functions:
generate: generate i numbers with a value from 0 to j.
prinTable: print the table.
renderDots: adds styles at the dots which match with the array values.
seleccion: execute the "Selection" way to organize the array.
highlight: adds styles at the dots which will be exchanged at THIS loop, and remove highlight styles of the others points.
I would like to get an affect like this:
You can use the setInterval function instead of a for loop:
function seleccion(table){
var ordenados = 0;
var timer = setInterval(renderOneStep, 300)
function renderOneStep(){
if (ordenados < table.length){
// do all the calculations
ordenados++;
} else {
clearInterval(timer);
}
}
}
The renderOneStep function updates one column. It is called every 300ms.
Please see the updated jsfiddle.
Related
So i want to make a changing series of images. They are saved in an array. So i can find each one by using image[i].
I want to make a for loop, or something similar, that will start at index 0, use a setInterval to make the index++. Lets say it goes up to five images. So i need a loop that will reset to 0 when it reaches index of 4.
I cant make this work. I thought it would be easy. Can anyone recommend a loop type?
Various for loops and useEffect
You don't need a for loop. If you have index and setInterval, then every function call of interval function can be treated like a loop cycle.
const images = [
"a.png",
"b.jpeg",
"c.gif"]
let i = -1
let update = () => {
i++
i = i % images.length
console.log(images[i])
}
setInterval(update,1000)
As the function will i++ we need to set initial i=-1 so it'll get 0 when added one. Otherwise, 0++ would be 1, and your images would start showing from second element.
Problem is that setTimeout function within for loop is not getting the correct values despite the fact they were passed correctly. Second problem is that the sleep variable is not working, it simply ignores it. Other variables like i are acting strange, they are not going though the loop, they are going in a random order.
Inside function set_delay
console.log(i);
// 3,5,0,2,4,1 should be 0,1,2,3,4,5
console.log(sleep);
// 6000,6000,7000,9000,9000,10000, those ones are displayied in ASC order but shuold be randomly
console.log(share_screen_rate[i]);
//4,1,6,10,6,2,8 - this is not ok it's random
console.log(top);
// 749.5,2998,299.8,499.667,149,374.75 => this should be in order from smallest (149) to biggest (2998)
setTimeout(function() {
}, sleep);
if I change sleep to a numeric value like 2000 it is respected only for first iteration after nothing, it just goes at 0ms.
FULL CODE
https://jsfiddle.net/ojpv2nxu/
EXPECTED OUTPUT
This should be a simple script to scroll down the page and make pause based on the sleep variable and also read the page chunk by chunk based on the share_screen_rate variable
I think it is a logic issue.... You are expecting the setTimeout to happen x seconds after the last one. But they are firing x seconds after you set it. So it is working as expected.
If you want them to fire x seconds after the last, than you need to change the logic to keep track of the seconds and adjust the timers.
so top of the file add
var timeTrack = 0
and than you need to add to that value
timeTrack += sleep
setTimeout(function() {
}, timeTrack);
I'm using a for loop to iterate through data from a weather API. Within that for loop, I'm assigning each night a rating on its suitability for stargazing (var totalRanking). Then I update a series of divs, having IDs day0, day1, etc., with this rating. (If it matters, these divs are being generated dynamically.) Here's the code block in question:
var dayRankLine = $("<div>");
var rating = $("<span class=rating>"); // happens
rating.text(Math.round(totalRanking * 100) + "%"); // happens
dayRankLine.html("Score: "); // happens
dayRankLine.append(rating); // doesn't happen on 0. (does on others)
$("#day" + i).after(dayRankLine); // happens (even on 0)
As shown in the comments, the first div, #day0, is getting text Score:, but no number. The remaining divs are working as expected. A later code block uses the rating for day 0 to update a different DOM element, and works as expected, showing that the correct value is getting input.
What's different about the first iteration through the loop, and what's different about appending, that that line should fail on that pass only?
Ohhh nevermind. As I said, I was using rating in a lower code block, and that was "stealing" it from day0. rating.clone() and problem solved.
This has been eating me away. Check CodePen here. I have a function that adds elements to a ruler. Call expose.init(lengthOfPeriod) with an integer to set the length of each period in the ruler. Call expose.addAction(time, team) with an integer and a string == 'HOME' || 'AWAY' to place an action in the ruler.
When the screen is resized, I want something to happen to the elements in the ruler that touch each other (basically collapse into a group).
I have a function 'detectOverlap' that takes 2 params and determines if they are touching or not. I also have a function in the resize event handler that populates an array 'allTouching' with all the elements in the ruler that are touching each other at each resize.
if (actionArray.length > 1) { //don't run if there's only one element in the page
actionArray.reduce(function (prev, next) {
if (detectOverlap(prev, next)) {
if (allTouching.indexOf(prev, next) === -1) allTouching.push(prev, next);
}
return next;
});
If actions are touching each other, I need them to collapse into groups. In order to do this, I need to create an array for each group of actions touching each other. However, I haven't been able to make this happen so far.
Here's some pseudo code:
for (i = 0; i < allTouching.length; i++) {
if (detectOverlap(allTouching[0], alltouching) {
touchingGroup[i] = new Array(allTouching[0], all other elements touched by 0);
do not include any element more than once in touchingGroup[i];
do not include any similar arrays (same elements) in allGroups;
allGroups.push(touchingGroup[i]);
}
}
In short, this would need to loop for all the elements in the allTouching array, and create a new touchingGroup[n] for each new group of actions that touch each other.
This sounds simple in my head, and I'm sure there must be a way to do it without code getting overly complex, but I haven't found it yet.
Any feedback would be appreciated.
It seems your question is only about the grouping, so I will ignore the visualisation aspect and assume that the function detectOverlap is correct.
Then you could create the groups in one for loop. In this snippet I have added simplistic sample data and a mock detectOverlap function that will return true when its two arguments are the same (just for the purpose of the snippet):
// Simplistic mock data and function, just to make the snippet work
var actionArray = [1, 1, 3, 3, 3, 8, 9];
function detectOverlap(a, b) { return a === b; }
// Actual code:
var allGroups = [];
var start = 0;
for (var i = 1; i <= actionArray.length; i++) {
if (i >= actionArray.length || !detectOverlap(actionArray[i-1], actionArray[i])) {
if (i - start > 1) // Remove this condition if you want singletons as well
allGroups.push(actionArray.slice(start, i));
start = i;
}
}
console.log(JSON.stringify(allGroups));
Explanation
The variable start is used as an index in the array, from where the most recently found group should start. That group is not yet actually created, since we do not know where it ends, and so I will call this the "undecided" group. start is initialised at 0 to indicate that the first group will start there.
The loop iterates over the array, but starting at 1. In each iteration it decides whether the "undecided" group (started at start) is complete. The group is considered complete when there is no overlap between the previous and the current element of the array. In that case the previous element is the last element of the "undecided" group. The elements for that group are copied from the array with slice. Note that the second argument of slice is the index of the first element that should not be part of the group. Now that group is stored, and start is put at the current index, where the next (and only) "undecided" group should start.
But as long as the two elements do overlap, no new group should be created (that is why the condition has a !). Instead start remains unchanged, and so this "undecided", "unclosed" group is getting bigger in size.
There is an if just before that slice, which prevents the creation of groups that only contain one element. If you remove that if, then also single elements will be isolated in their own "singleton" groups.
The loop will go up to and including arrayAction.length: this is unusual, since that makes the last i an invalid index. But it is useful, since in that case we still want to finish up the last group that is still "ongoing". So in that case i >= arrayAction.length will be true, and so the detectOverlap function will not be called (because the if condition is already known to be true). The if block will be entered and the final group will be created.
We have followed Tom Anthony's tutorial to calculate a geocode from a UK postcode to plot a marker on a Google Map. This has worked fine, but now we wish to add a popup when you click on a location. So we updated our function to place a marker and original usePointFromPostcode code to take in a description:
function usePointFromPostcode(postcode, description, callbackFunction) {
localSearch.setSearchCompleteCallback(null,
function() {
if (localSearch.results[0]) {
var resultLat = localSearch.results[0].lat;
var resultLng = localSearch.results[0].lng;
var point = new GLatLng(resultLat,resultLng);
callbackFunction(point, description);
}else{
alert("Postcode not found!");
}
});
localSearch.execute(postcode + ", UK");
}
// loop through the array of postcodes to output markers
for(var i=0; i<postcodes; i++) {
usePointFromPostcode(postcodes[i], descriptions[i], placeMarkerAtPoint);
}
However, whilst the page loads without error, the markers all have the same description - that of the last item in the array. I believe this is due to a closure, or rather a lack of one, but am unable to hack out the solution. How can we get the descriptions in sync with the points?
If localsearch.execute initiates a search but returns before the search is complete, then that would explain the behaviour. Two possible solutions. Create a separate GlocalSearch object for each query or delay issuing the second query until the first is complete, etc.
I don't know enough about the GlocalSearch class to say if the former is sensible. If it is, you presumably will have several searches running in parallel that may finish in arbitrary order.
To do the later: Alter your callback to set a global flag done to true. Before initiating the first search, set done to false. After initiating the first search, set a timeout. The code executed by the timeout does the following: if done is now true, it sets done to false and initiates the second search. Otherwise, it simply repeats the same timeout. And of course this sort of thing repeats until all searches are complete, at which point the time out code initiates whatever you want to do after that loop. See http://www.ehow.com/how_4847411_simulate-whilesleep-loop-javascript.html for a short article that may be helpful.