Why is my array separating itself out in Javascript? - javascript

So I'm trying to make this smooth color fade transition for my website. I made a function that should do just that, and it even looks like it would work, but I am having a problem I do not understand in the least, nor have I even seen anything like it before. I am using recursion in my function and passing a color I changed back into the function to be changed again. I only exit when the current color matches the target color. What I have COMPLETELY CONFIRMED is happening is that when I pass the 2 arrays back into the function again, they split themselves apart.
Ex: before being passed through, startColsAr=[211, 211, 211].
after being passed through, startColsAr=['2'; '1'; '1'; ','; '2'; '1'; '1'; ','; '2'; '1'; '1'].(semi-colons were used to make reading easier).
As you can see in my function below, nowhere am I doing anything to change the contents of the arrays like that.
Here is my function:
function transitionOut(startColAr,endColAr, waitTime, interval, page){
//change the colors
for(var i=0;i<3;i++){
if(startColAr[i]<endColAr[i]){
startColAr[i]+=interval;
if(startColAr[i]>endColAr[i]){startColAr[i]=endColAr[i];}
}else if(startColAr[i]>endColAr[i]){
startColAr[i]-=interval;
if(startColAr[i]<endColAr[i]){startColAr[i]=endColAr[i];}
}
}
//var color="rgb("+startColAr[0]+", "+startColAr[1]+", "+startColAr[2]+")";
var color = "#"+startColAr[0].toString(16)+startColAr[1].toString(16)+startColAr[2].toString(16);
document.body.style.backgroundColor = color;
if(startColAr[0]==endColAr[0] && startColAr[1]==endColAr[1] && startColAr[2]==endColAr[2]){
location.href=page;
}
window.setTimeout("transitionOut(\'"+startColAr+"\', \'"+endColAr+"\', \'"+delay+"\', \'"+interval+"\', \'"+page+"\')",waitTime);
}
Now, I am only passing in 3 values for both arrays, so I could easily change the 2 arrays to 6 integer parameters(and probably get the function to work(so don't tell me to go download a new library for transitions, THIS IS ABOUT ARRAYS)), but I want to know why this is happening. Does anyone have any suggestions? I have tried a bunch of different things to narrow it down, but I can't seem to put a dent in this at all. A little help?

The problem is with the line:
window.setTimeout("transitionOut(\'"+startColAr+"\', \'"+endColAr+"\', \'"+delay+"\', \'"+interval+"\', \'"+page+"\')",waitTime);
You are converting your arrays into strings when you are preparing the code to be run later. As per the Mozilla doc, it would probably be easier to use the alternate form of the setTimeout function:
window.setTimeout(transitionOut, waitTime, startColAr, endColAr, waitTime, interval, page);

I think this line is your problem
window.setTimeout("transitionOut(\'"+startColAr+"\', \'"+endColAr+"\', \'"+delay+"\', \'"+interval+"\', \'"+page+"\')",waitTime);
You probably want something like
window.setTimeout(transitionOut, waitTime, startColAr, endColAr, waitTime, interval,page,waitTime);
You can call setTimeout with a string literal but I don't think it's recommended.

Related

Create a re-usable type writer effect function in Javascript?

I know the basics of what I need to do here, but my attempt at coding it is riddled with problems so here is what I want to do.
Define a series of strings to be called up into a function that types it onto the screen with a slight delay between each letter.
I've found some examples of people making typewriter title cards, but these are not designed to be used like functions that can be called up on the fly. For this particular project, we need the text to function like a makeshift dialog system that won't be called up until the function is called with a specific string.
Like a button with " onclick="dialogFunction(idOfStringToBeTyped) "
what I have looks like this:
var d1Example = "Hello, I am example dialog";
function dialog(dialogString) {
var i;
for (i = 0; i <= dialogString.length(); i++) {
document.write( dialogString.charAt(i) );
java.lang.Thread.sleep(50);
}}
So my attempts to code the content has been... brute force-y...
EDIT: to include my attempt, should have been there in the first place, sorry about that.
This, in theory, should work, but in practice does nothing. I probably have a syntax error. but really it doesn't make sense to me why this doesn't work.
You should look into the JavaScript functions setTimeout and Math.random().
You can use Math.random() to create a floating point integer between 0 and 1.
var multipule = 5
var rand = Math.random(); // 0.5680401974599227
var randInSeconds = rand * multipule // 2.840200987299614
var waitInSeconds = Math.round(randInSeconds) // 3
Then use the the setTimeout out method to call the code that writes each character. setTimeout takes two parameters, a function and the number of seconds:
var writeCharacter = function(){
...
};
setTimeout(writeCharacter, 300);
I'll leave it to you to work out all the timing.

Game loop appears to be breaking at the end of iterating through array. Uncaught TypeError

Morning all,
Definitely a novice question here, this is my first real JS project - so apologies in advance for the clunky code.
The following functions are being used to show the light sequence for a "simon" game. The code seems to work fine initially, as I've tested multiple lengths of array, however on exiting the loop I get the following error:
Uncaught TypeError: Cannot read property 'setAttribute' of null
at show (script.js:95)
at showLights (script.js:83)
at script.js:88
I've looked around a lot for fixes to this error, and the majority of feedback is that it's related to the DOM and a wrapper will fix. I've found that a wrapper doesn't resolve. Similarly, I can't see that it's an issue with the CSS or HTML as the functions work ok until exit.
The looping functions are copied below:
// iterates through simon.array then allows button press
function showLights(x) {
if (x >= simon.array.length) {
clearTimeout(timer);
show(x);
allowPress();
} else {
show(x);
var timer = setTimeout(function(){
showLights(x+1);
},500);
}
}
// adds then removes flash class to light pads.
function show(x){
var display = document.getElementById("light" + simon.array[x]);
display.setAttribute("class", "flasher");
setTimeout(function(){
display.setAttribute("class", "game-box");
},500);
}
Apologies in advance for any errors or faux pas in posting this. I strongly suspect that I'll be kicking myself when this is fixed.
Kind Regards
Andy
The issue is related to you checking the length of an array, then trying to use an element of that array that does not exist. You are possibly also trying to set an attribute to an element that does not exist.
At a guess, this is the real cause of the issue:
if (x >= simon.array.length) {
clearTimeout(timer);
show(x);
allowPress();
Simply removing show(x) should help. The reason is you are checking for the length of simon.array, then later in function show(x) you make a request for simon.array[x], but that is not going to find anything, as x is greater than the length of that array.
The other possible issue is in the following chunk, but could be solved a number of ways. One way is to check x before passing. Another is making sure the element (display) is not null before setting the attribute.
// adds then removes flash class to light pads.
function show(x){
var display = document.getElementById("light" + simon.array[x]);
display.setAttribute("class", "flasher");
setTimeout(function(){
display.setAttribute("class", "game-box");
},500);
}
My suggestion would be as follows:
// adds then removes flash class to light pads.
function show(x){
var display = document.getElementById("light" + simon.array[x]);
if (display) {
display.setAttribute("class", "flasher");
setTimeout(function(){
display.setAttribute("class", "game-box");
},500);
}
}
You may want to check out classList as well as an alternative to setAttribute.
Something else to consider instead of using setTimeout would be to use a CSS animation.

Wait before start new loop at FOR - JS

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.

Javascript code causing IE freeze

I have the below code causing Internet Explorer to freeze. It's a project that involves processing student grades as an assignment:
var array1 = StudentGradeAreadHugeList();
var nextArrayItem = function() {
var grade = array1.pop();
if (grade) {
nextArrayItem();
}
};
i hope you can help me with this.
You could show more info about the application you're trying to do. But I believe it's a matter of stack overflow (maybe you're using a big list). So, to overcome that you should modify the "nextArrayItem":
window.setTimeout (nextArrayItem, 0)
The freeze incurring mainly from the big data, but now the Event Loop will handle the Recursion process and not your Call Stack.
This is likely caused by an endless recursion. Be aware of proper handling of return values in IE:
var array1 = StudentGradeAreadHugeList();
var nextArrayItem = function() {
var grade = array1.pop();
if ( grade !== null && typeof(grade) !== "undefined" ) {
nextArrayItem();
}
};
pop() on an empty array will not return boolean false but a typeless "undefined".
There's two problems here:
You might be exceeding the call stack limit
Your if-conditional is set-up incorrectly
For the first issue:
As one of the previous responders mentioned, if you have a very large list you can exceed the limit of the call stack since you need to do a recursive call for each element. While doing setTimeout might work, it feels like a hack-y solution. I think the real issue is that your function is handling the array recursively rather than iteratively. I would recommend re-writing your function using a for-loop.
For the second issue:
Let's say in this case your array was set to [100, 90, 80]. When you invoke nextArrayItem() it will work properly the first two time, but the third time you call nextArrayItem() you are popping off the last remaining item (in this case 100) and your grade will be set to 100 which is a truthy value. Therefore, your if-conditional will pass and your function erroneously try to invoke itself again despite the fact that your array is now empty and the program should now exit the call stack.
I tried testing your code using my example in Chrome and what happens is that it will recurse one too many times and invoke pop on an empty array, which will return undefined.
You can fix this issue by changing the if conditional to check for the last element in the array after you have popped the array.
See revised code:
var nextArrayItem = function() {
var grade = array1.pop();
if (array1[array1.length-1]) {
nextArrayItem();
}
};

slide a div using javascript

I wanted to write a javascript code that will slide a div in specific direction, distance and in some given time. I wrote this small script. but doesn't work at all. Instead browser gets slow. No change in position is visible.
Can someone tell me how to achieve the result ? I know there are many ready made libraries that can do this easily. But I just wanted to give it a try.
<script type="text/javascript" language="javascript">
var element = '';
var slidePerMS = '';
function slideIt(ele, direction, distance, slideDuration){
element = ele;
var i=0;
slidePerMS = distance / (slideDuration*1000);
for(i=0; i<3000; i++){
setTimeout("changePosition()",1);
}
}
function changePosition(){
var currElement = document.getElementById(element);
currElement.style.left = "'"+slidePerMS+"px'";
}
</script>
SOO many things wrong with that code it's not even funny... Let's see...
You are trying to render a 1,000 FPS animation. This is simply impossible for a browser.
You are passing a string as parameter to setTimeout, which is as evil as eval.
You set slidePerMS once but never change it after, resulting in the div being moved to the exact same spot over and over.
You are setting the style with extra quotes inside - do you put quotes in a CSS file?
That's to name but a few. Try this instead:
<script type="text/javascript" language="javascript">
function slideIt(elem, direction, distance, slideDuration){
var elmt = document.getElementById(elem),
i=0, step = distance / (slideDuration*20),
stepper = setInterval(function() {
i = Math.min(distance,i+step);
elmt.style.left = i+'px';
if( i == distance) clearInterval(stepper);
},50);
}
</script>
You have many problems.
You are treating setTimeout as if it was sleep. Don't do that. It isn't like sleep at all, it runs a function after a given period of time, but doesn't pause the execution of anything else.
This means you just hammer the function repeatedly 3000 times, which is what is locking up the browser.
Instead of using a for loop, you should be using setInterval.
Don't pass a string to setInterval (or setTimeout), it gets evaled, which is slow and hard to debug, and it breaks scope. Pass a function instead.
Inside changePosition you are trying to use a variable called slidePerMS, which is undefined because it is defined in the scope of slideIt.
You are also trying to set left to "'123px'". You can't quote your values in CSS.
Get rid of both the 's.
This is why you can't see any change. Invalid values are ignored in CSS.

Categories

Resources