function moveDoi(n) {
var delay = -1;
var left = document.getElementById("One");
var currentLeft = parseInt(getComputedStyle(left).left, 10);
setTimeout(move, delay);
function move(){
if (currentLeft <= n ) {
currentLeft+=3;
left.style.left = currentLeft + "px";
setTimeout(move, delay);
}
}
};
In this code I have n as a parameter of the function, that is used in the if conditional statement.
For this function i need to have one more parameter x that will change the "One" so i need to obtain something like this: document.getElementById(""+x+"") . However, this is not working?
How can I add one more parameter to the function that needs to be in quotes (" ") in function?
First, you need to pass x into the function. Then, you simply need to reference it when calling document.getElementById. There are is no need to append/prepend quotes, since x is already a string.
function moveDoi(n, x) {
var delay = -1;
var left = document.getElementById(x);
var currentLeft = parseInt(getComputedStyle(left).left, 10);
setTimeout(move, delay);
function move(){
if (currentLeft <= n ) {
currentLeft+=3;
left.style.left = currentLeft + "px";
setTimeout(move, delay);
}
}
};
Related
So, I have a page, where when a user holds left mouse button, Shrek images are drawn where his/her cursor is. The problem is, only one picture is created when the mouse is down, but I need an ENDLESS CURRENT OF SHREKS.
Here is the code:
var shrekId = 0;
document.onmousemove = function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
}
window.addEventListener('selectstart', function(e){ e.preventDefault(); });
document.body.onmousedown = function(event) {
shrekId = 0;
interval = setInterval(draw(event), 100);
}
document.body.onmouseup = function() {
clearInterval(interval);
}
function draw(event) {
this["img" + shrekId] = document.createElement("img");
this["img" + shrekId].src = "http://pngimg.com/uploads/shrek/shrek_PNG3.png";
this["img" + shrekId].style = "height: 100px; width: 100px; position: absolute; left: " + (mouseX - 50) + "px; top: " + (mouseY - 50) + "px; x-index: 100;";
this["img" + shrekId].ondragstart = function() { return false; };
document.body.appendChild(this["img" + shrekId]);
shrekId += 1
}
setInterval() takes a function as a parameter, this is done by passing the function name (without the brackets) like so:
myFunc()
{
console.log('hello');
return 1;
}
setInterval(myFunc, 100);
When you do include the brackets (like you did in your example), it will run the function, take the return of that function, and provide that to the setInterval instead.
For example:
myFunc()
{
console.log('hello');
return 1;
}
setInterval(myFunc(), 100);
turns into
setInterval(1, 100);
because myFunc() returns 1.
So you should be able to fix your code by removing the brackets from your interval:
interval = setInterval(draw(event), 100);
// to
interval = setInterval(draw, 100);
Which also means you have to remove the parameter from the function:
function draw(event) {
// to
function draw() {
The problem is with this line: interval = setInterval(draw(event), 100);
The first parameter of setInterval should be a function, but you're calling the function here and passing in the result, try the following instead:
interval = setInterval(() => { draw(event) }, 100);
Or if you aren't supporting ES6:
interval = setInterval(function() { draw(event) }, 100);
It doesn't look like you're using event inside of the draw function though, if that's the case you can just pass the draw function itself:
interval = setInterval(draw, 100);
You are passing the result of executing the function instead of the function itself. Since the result of the function is undefined, you are executing draw and then passing undefined to setInterval which doesn't do anything.
Instead of this:
setInterval(draw(), 100);
Your statement should be this:
setInterval(draw, 100);
without the parentheses at the end of the function name.
When you pass draw() that calls the function immediately and gets it's return value. When you pass draw that passes a reference to the function so setInterval can invoke it in future(which is what you expect).
I have a code which I am trying to execute using a parameter in the function, i.e -
function startFadeEffect(elem){ };
I have made the elem equal to a variable b in the global scope, where b is an array of images. Meaning -
var elem = b[imgNumb];
imgNumb is a variable which is globally "0" and inside a function is defined as
imgNumb = imgNumb + count;
Now, my current code "without" the parameter works perfect -
function startFadeEffect(){
var opacSetting = noOpac / 10;
b[imgNumb].style.opacity = opacSetting;
b[imgNumb].style.display = "block";
noOpac++;
if(noOpac < 0){
opacSetting = 0;
}
if(opacSetting == 1){
clearTimeout(timer);
b[imgNumb].style.opacity = 1;
noOpac = 0;
return false;
}
var timer = setTimeout(startFadeEffect, 75);
}
However, when I use the parameter like this it does not work for me :(
function startFadeEffect(elem){
var opacSetting = noOpac / 10;
elem.style.opacity = opacSetting;
elem.style.display = "block";
noOpac++;
if(noOpac < 0){
opacSetting = 0;
}
if(opacSetting == 1){
clearTimeout(timer);
elem.style.opacity = 1;
noOpac = 0;
return false;
}
var timer = setTimeout(startFadeEffect(elem), 75);
}
Please note I have already defined the elem variable in the global scope of the file. Also, I am only looking for a JS solution no library like JQuery! Thanks
This part is incorrect:
setTimeout(startFadeEffect(elem), 75);
It should be:
setTimeout(function () {
startFadeEffect(elem);
}, 75);
setTimeout expects a function as it's first argument. startFadeEffect(elem) is executed immediately (and doesn't return a function). So what happens is that startFadeEffect calls itself recursively until opacSetting == 1 which breaks the recursion.
So I'm new to javascript and I am looking for a way to count how many times a function is executed. The code randomly generates a square or circle and displays from the shape is shown to when you click it (reactionTime). That works fine and dandy.
But I'm looking for a way to keep track of the number of times a shape is clicked and then eventually the cumulative time to calculate average time per click. If it helps, I come from a pretty good C++ background.
To count number of clicks, I was thinking of adding a closure function.
From here: How do I find out how many times a function is called with javascript/jquery?
myFunction = (function(){
var count = 0;
return function(){
count++
alert( "I have been called " + count + " times");
}
})();
And from here: Function count calls
var increment = function() {
var i = 0;
return function() { return i += 1; };
};
var ob = increment();
But I tried a global variable and several variations of closure functions to no avail (look for the comments). I tried putting the closure function in other functions. And I also tried something like:
var increment = makeBox();
I'm wondering if anyone can guide me in the right direction. It would be much appreciated!
var clickedTime; var createdTime; var reactionTime;
var clicked; var avg = 0;
avg = (avg + reactionTime) / clicked;
document.getElementById("clicked").innerHTML = clicked;
document.getElementById("avg").innerHTML = avg;
function getRandomColor() {
....
}
function makeBox() { // This is the long function that makes box
createdTime = Date.now();
var time = Math.random();
time = time * 3000;
///////// var increment = function () {
var i = 0;
//return function() { return i += 1; };
i++;
return i;
///////// };
// clicked++; /////////// global variable returns NaN
// console.log(clicked);
// alert("Clicked: "+clicked);
setTimeout(function() {
if (Math.random() > 0.5) {
document.getElementById("box").style.borderRadius="75px"; }
else {
document.getElementById("box").style.borderRadius="0px"; }
var top = Math.random(); top = top * 300;
var left = Math.random(); left = left * 500;
document.getElementById("box").style.top = top+"px";
document.getElementById("box").style.left = left+"px";
document.getElementById("box").style.backgroundColor = getRandomColor();
document.getElementById("box").style.display = "block";
createdTime = Date.now();
}, time);
}
ob = increment(); //////////////////////// I think this gives me 1 every time
alert("Increment: "+ob); //////////////////
document.getElementById("box").onclick = function() {
clickedTime = Date.now();
reactionTime= (clickedTime - createdTime)/1000;
document.getElementById("time").innerHTML = reactionTime;
this.style.display = "none";
makeBox();
}
makeBox();
You have a few problems but to answer your question:
You're not defining clicked as a number (or any other type) so trying to perform an operation on undefined returns NaN...because well, it's not a number.
Your second attempt var i = 0; won't work because i is re-defined on each function call.
You should be able to use your gobal variable clicked as long as you set it to zero.
Here is an example that shows how a closure can count calls to a function:
function add5(y) {
//A totally normal function
return y + 5;
}
var counter = 0, /*a counter scoped outside of the function counter function*/
trackedAdd5 = (function (func) {
/*This anonymous function is incrementing a counter and then calling the function it is passed*/
return function () {
counter++;
/*The trick is this function returns the output of calling the passed in function (not that it is applying it by passing in the arguments)*/
return func.apply(this, arguments);
}
})(add5); /*calling this tracking function by passing the function to track*/
document.getElementById('run').addEventListener('click', function () {
/*Here we are treating this new trackedAdd5 as a normal function*/
var y = document.getElementById('y');
y.value = trackedAdd5(parseInt(y.value, 10));
/*Except the outer counter variable now represents the number of times this function has been called*/
document.getElementById('counter').value = counter;
});
<label> <code>y = </code>
<input id='y' value='0' />
<button id='run'>add5</button>
</label>
<br/>
<label><code>add5()</code> was called
<input readonly id='counter' value='0' />times</label>
makeBox.click = 0; // define the function's counter outside the function
makeBox.click++; // replace the `i` usage with this inside the function
About ob = increment();: it is used erroneously (redefines ob many times);
var ob = increment(); // define it once
ob(); // increments the counter
// another way to define `increment`:
var increment = (function () {
var i = 0;
return function () {
return i += 1;
};
})();
ob = increment(); // ob becomes 1 initially
ob = increment(); // ob becomes 2, etc.
Hi friends i want to fade in a div when i click on another div and for that i am using following code. Code1 works fine but i require to use the Code2.
I know there is jQuery but i require to do this in JavaScript
Can you guide me that what kind of mistake i am doing or what i need change...
Code1 --- Works Fine
function starter() { fin(); }
function fin()
{
for (i = 0; i <= 1; i += 0.01)
{
i=Math.round(i*100)/100;
setTimeout("seto(" + i + ")", i * 1000);
}
}
function seto(opa)
{
var ele = document.getElementById("div1");
ele.style.opacity = opa;
}
Code2 --- Does not work
function starter()
{
var ele = document.getElementById("div1");
fin(ele);
}
function fin(ele)
{
for (i = 0; i <= 1; i += 0.01)
{
i=Math.round(i*100)/100;
setTimeout("seto(" + ele + "," + i + ")", i * 1000);
}
}
function seto(ele,opa)
{
ele.style.opacity = opa;
}
Based on this site
EDIT-1
Added the functionality so that user can specify the animation duration(#Marzian comment)
You can try this:
function fadeIn(el, time) {
el.style.opacity = 0;
var last = +new Date();
var tick = function() {
el.style.opacity = +el.style.opacity + (new Date() - last) / time;
last = +new Date();
if (+el.style.opacity < 1) {
(window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
}
};
tick();
}
var el = document.getElementById("div1");
fadeIn(el, 3000); //first argument is the element and second the animation duration in ms
DEMO
Update:
It seems that people enjoy my minimalistic and elegant approach, Updated for 2022:
No need for complex mechanisms. Just use CSS, which has it out of the box and has better performance overall.
Basically you achieve it with CSS by setting a transition for the opacity. In JavaScript that would be:
const div = document.querySelector('#my-div');
div.style.transition='opacity 1s';
and as a trigger you just set opacity to 0:
div.style.opacity=0;
This will create a 1 second fade out effect and you can use the trigger anywhere. The inverse can also be done to achieve a fade in effect.
Here's a working example:
const div = document.querySelector('#my-div');
div.style.transition='opacity 1s';
// set opacity to 0 -> fade out
setInterval(() => div.style.opacity=0, 1000);
// set opacity to 1 -> fade in
setInterval(() => div.style.opacity=1, 2000);
#my-div { background-color:#FF0000; width:100%; height:100%; padding: 10px; color: #FFF; }
<div id="my-div">Hello!</div>
Seems like your attempting to convert your element, to a string. Try this instead
function starter()
{
var ele = document.getElementById("div1");
fin(ele);
}
function fin(ele)
{
for (i = 0; i <= 1; i += 0.01)
{
i=Math.round(i*100)/100;
setTimeout(function() { setto(ele,i); }, i * 1000);
}
}
function seto(ele,opa)
{
ele.style.opacity = opa;
}
What happens here is, that i call a anonnymous function when the timer hits, and from that function, execute my functioncall to setto.
Hope it helps.
Jonas
The problem here is you are using the pass-a-string method of using setTimeout. Which is basically just a hidden eval.
It's worth noting that this is a bad practice, slow performer, and security risk.
(see questions such as this: setTimeout() with string or (anonymous) function reference? speedwise)
The reason this is causing your problem is because "seto(" + ele + "," + i + ")" is going to evaluate to "seto('[object HTMLDivElement]', 1)". You really want to pass reference to the ele object -- but the value's being cast to a string when you tried concatenating an object onto a string. You can get around this by using the pass-a-function method of using setTImeout.
setTimeout(function() { seto(ele, i); }, i * 1000);
I believe making this change will make your Code2 behavior equivalent to Code1.
Below are the complete answers to my question
ANS1 --- DEMO
function fin() {
var i = 0;
var el = document.getElementById("div1");
fadeIn(el,i);
}
function fadeIn(el,i) {
i = i + 0.01;
seto(el,i);
if (i<1){setTimeout(function(){fadeIn(el,i);}, 10);}
}
function seto(el,i) {
el.style.opacity = i;
}
ANS2 --- DEMO
function fin(){
var i = 0;
var el = document.getElementById("div1");
fadeIn(el,i);
}
function fadeIn(el,i) {
var go = function(i) {
setTimeout( function(){ seto(el,i); } , i * 1000);
};
for ( i = 0 ; i<=1 ; i = i + 0.01) go(i);
}
function seto(el,i)
{
el.style.opacity = i;
}
My version
function fadeIn($element){
$element.style.display="block";
$element.style.opacity=0;
recurseWithDelayUp($element,0,1);
}
function fadeOut($element){
$element.style.display="block";
$element.style.opacity=1;
recurseWithDelayDown($element,1,0);
}
function recurseWithDelayDown($element,startFrom,stopAt){
window.setTimeout(function(){
if(startFrom > stopAt ){
startFrom=startFrom - 0.1;
recurseWithDelayDown($element,startFrom,stopAt)
$element.style.opacity=startFrom;
}else{
$element.style.display="none"
}
},30);
}
function recurseWithDelayUp($element,startFrom,stopAt){
window.setTimeout(function(){
if(startFrom < stopAt ){
startFrom=startFrom + 0.1;
recurseWithDelayUp($element,startFrom,stopAt)
$element.style.opacity=startFrom;
}else{
$element.style.display="block"
}
},30);
}
function hide(fn){
var hideEle = document.getElementById('myElement');
hideEle.style.opacity = 1;
var fadeEffect = setInterval(function() {
if (hideEle.style.opacity < 0.1)
{
hideEle.style.display='none';
fn();
clearInterval(fadeEffect);
}
else
{
hideEle.style.opacity -= 0.1;
}
}, 20);
}
function show(){
var showEle = document.getElementById('myElement');
showEle.style.opacity = 0;
showEle.style.display='block';
var i = 0;
fadeIn(showEle,i);
function fadeIn(showEle,i) {
i = i + 0.05;
seto(showEle,i);
if (i<1){setTimeout(function(){fadeIn(showEle,i);}, 25);}
}
function seto(el,i)
{
el.style.opacity = i;
}
}
hide(show);
I just improved on laaposto's answer to include a callback.
I also added a fade_out function.
It could be made more efficient, but it works great for what i'm doing.
Look at laaposto's answer for implementation instructions.
You can replace the JS in his fiddle with mine and see the example.
Thanks laaposto!
This really helped out for my project that requires zero dependencies.
let el = document.getElementById( "div1" );
function fade_in( element, duration, callback = '' ) {
element.style.opacity = 0;
let last = +new Date();
let tick = function() {
element.style.opacity = +element.style.opacity + ( new Date() - last ) / duration;
last = +new Date();
if ( +element.style.opacity < 1 )
( window.requestAnimationFrame && requestAnimationFrame( tick ) ) || setTimeout( tick, 16 );
else if ( callback !== '' )
callback();
};
tick();
}
function fade_out( element, duration, callback = '' ) {
element.style.opacity = 1;
let last = +new Date();
let tick = function() {
element.style.opacity = +element.style.opacity - ( new Date() - last ) / duration;
last = +new Date();
if ( +element.style.opacity > 0 )
( window.requestAnimationFrame && requestAnimationFrame( tick ) ) || setTimeout( tick, 16 );
else if ( callback !== '' )
callback();
};
tick();
}
fade_out( el, 3000, function(){ fade_in( el, 3000 ) } );
Cheers!
I'm trying to gradually increase the elements of 2 id's in javascript using a Timeout. I can get one working but when trying to call another element into the same function it only does one iteration then crashes after the first recursive call.
I'm passing two id's for the elements. and I want the left element to gradually increase while the right element gradually increases in width.
Heres what ive got
function grow(elementL, elementR)
{
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
clearTimeout(loopTimer);
return false;
}
var loopTimer = setTimeout('grow(\''+elementL+','+elementR+'\')',50);
}
You could simplify this (removing the script-generation) by using setInterval -- this repeats the function call until you cancel it.
function grow(elementL, elementR)
{
var loopTimer = setInterval(function() {
if (!growStep(elementL, elementR)) {
clearInterval(loopTimer);
}
}, 50);
}
function growStep(elementL, elementR) {
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
return false;
}
return true;
}
(Fiddle)
Edit
Yeah, I guess the only problem with the OP code is that it passes a string to setTimeout, rather than the function itself:
var loopTimer = setTimeout(function() {
grow(elementL, elementR);
},50);
setTimeout('grow(\''+elementL+','+elementR+'\')',50)
would need to be
setTimeout('grow(\''+elementL+'\',\''+elementR+'\')',50)
// ^^ ^^
to work. But don't do that. Pass a function expression to setTimeout:
setTimeout(function() {
grow(elementL, elementR);
}, 50)