How to call a function only for the first time - JavaScript - javascript

Note: I need to achieve this with pure javascript, I know there is a .one() method in jquery to do this, but I need the same output in pure javascript.
Scenario: I am trying to call a function when a user scrolls and reaches to the 3/4 part or more of the page, but the problem rises when user reaches that part, We all know they can't be pixel perfect so, after the condition is met, the function gets executed per pixel scroll.
I want that to execute only once the condition is met, then add a section at the bottom of the page, and then again user should reach the bottom and the function should get executed only once and so on...
Snippet:
var colors = ['skyblue', 'powderblue', 'lightgreen', 'indigo', 'coral'];
var addPage = function() {
var page = document.createElement('div');
page.classList.add('page');
page.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
document.body.append(page);
console.log('added a new page');
}
var scrollAndAdd = function() {
if (window.scrollY < (window.innerHeight * (3 / 4))) {
// execute addPage only once for each attempt; it's creating infinite pages
addPage();
}
}
window.addEventListener('scroll', scrollAndAdd);
* {
margin: 0;
padding: 0;
}
.page {
height: 100vh;
}
<div class='page' style='background-color: lightgreen'></div>
<div class='page' style='background-color: skyblue'></div>

You don't really need logic to run the function just once; instead, use a different expression to determine whether to add the page. Once the page is added that same expression should no longer evaluate to true until more scrolling is done.
NB: I also changed a bit the random pick logic.
var colors = ['powderblue', 'lightgreen', 'indigo', 'coral', 'skyblue'];
var addPage = function() {
var page = document.createElement('div');
page.classList.add('page');
// Make sure the same color is not selected twice in sequence:
var colorIndex = Math.floor(Math.random() * (colors.length-1));
var color = colors.splice(colorIndex,1)[0];
colors.push(color);
page.style.backgroundColor = color;
document.body.append(page);
}
var scrollAndAdd = function() {
if (window.scrollY > document.body.clientHeight - window.innerHeight - 10) {
addPage();
}
}
window.addEventListener('scroll', scrollAndAdd);
* {
margin: 0;
padding: 0;
}
.page {
height: 100vh;
}
<div class='page' style='background-color: lightgreen'></div>
<div class='page' style='background-color: skyblue'></div>

I hope it will help you:
var colors = ['skyblue', 'powderblue', 'lightgreen', 'indigo', 'coral'];
var addPage = function() {
var page = document.createElement('div');
page.classList.add('page');
page.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
document.body.append(page);
console.log('added a new page');
}
var scrollAndAdd = function() {
var a = document.body.clientHeight - window.innerHeight * (5 / 4)
if (window.scrollY > a) {
addPage();
}
}
window.addEventListener('scroll', scrollAndAdd);
* {
margin: 0;
padding: 0;
}
.page {
height: 100vh;
}
<div class='page' style='background-color: lightgreen'></div>
<div class='page' style='background-color: skyblue'></div>

Well how about curry it up with local flag.
var colors = ['skyblue', 'powderblue', 'lightgreen', 'indigo', 'coral'];
const localCurry = function(func, immediateAction) {
var flag;
return function() {
var context = this, args = arguments;
var callNow = immediateAction && !flag;
flag = true;
if (callNow) func.apply(context, args);
}
}
var addPage = localCurry(function() {
var page = document.createElement('div');
page.classList.add('page');
page.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
document.body.append(page);
console.log('added a new page');
}, true);
var scrollAndAdd = function() {
var a = document.body.clientHeight - window.innerHeight * (5 / 4)
if (window.scrollY > a) {
addPage();
}
}
window.addEventListener('scroll', scrollAndAdd);
Now you do have option to reset the flag based on timer or custom logic.

Related

Random movement of circles created by the script

I have a function that craeates divs with a circle.
Now they are all created and appear at the beginning of the page and go further in order.
Next, I need each circle to appear in a random place. I did this.
Now I need all of them to move randomly across the entire page, I have difficulties with this.
Here is an example of how everything works for one element that is already on the page.
https://jsfiddle.net/quej8wko/
But when I add this code, all my created circles don't move.
I get an error:
"message": "Uncaught TypeError: Cannot set properties of null (setting 'willChange')",
This is probably due to the fact that initially there are no circles on the page. How can I connect the code so that all created circles move?
//creating circles
var widthHeight = 40; // <-- circle width
var margin = 20; // <-- margin - is it necessary ?
var delta = widthHeight + margin;
function createDiv(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = document.documentElement.clientHeight;
var documentWidth = document.documentElement.clientWidth;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.backgroundColor = color;
}
div.classList.add("circle");
div.classList.add("animation");
// Get the random positions minus the delta
currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;
// Keep the positions between -20px and the current positions
var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";
document.body.appendChild(div);
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createDiv(`circle${i}`)
}, oneSecond);
//move circles
function RandomObjectMover(obj, container) {
this.$object = obj;
this.$container = container;
this.container_is_window = container === window;
this.pixels_per_second = 250;
this.current_position = { x: 0, y: 0 };
this.is_running = false;
}
// Set the speed of movement in Pixels per Second.
RandomObjectMover.prototype.setSpeed = function(pxPerSec) {
this.pixels_per_second = pxPerSec;
}
RandomObjectMover.prototype._getContainerDimensions = function() {
if (this.$container === window) {
return { 'height' : this.$container.innerHeight, 'width' : this.$container.innerWidth };
} else {
return { 'height' : this.$container.clientHeight, 'width' : this.$container.clientWidth };
}
}
RandomObjectMover.prototype._generateNewPosition = function() {
// Get container dimensions minus div size
var containerSize = this._getContainerDimensions();
var availableHeight = containerSize.height - this.$object.clientHeight;
var availableWidth = containerSize.width - this.$object.clientHeight;
// Pick a random place in the space
var y = Math.floor(Math.random() * availableHeight);
var x = Math.floor(Math.random() * availableWidth);
return { x: x, y: y };
}
RandomObjectMover.prototype._calcDelta = function(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt( dx*dx + dy*dy );
return dist;
}
RandomObjectMover.prototype._moveOnce = function() {
// Pick a new spot on the page
var next = this._generateNewPosition();
// How far do we have to move?
var delta = this._calcDelta(this.current_position, next);
// Speed of this transition, rounded to 2DP
var speed = Math.round((delta / this.pixels_per_second) * 100) / 100;
//console.log(this.current_position, next, delta, speed);
this.$object.style.transition='transform '+speed+'s linear';
this.$object.style.transform='translate3d('+next.x+'px, '+next.y+'px, 0)';
// Save this new position ready for the next call.
this.current_position = next;
};
RandomObjectMover.prototype.start = function() {
if (this.is_running) {
return;
}
// Make sure our object has the right css set
this.$object.willChange = 'transform';
this.$object.pointerEvents = 'auto';
this.boundEvent = this._moveOnce.bind(this)
// Bind callback to keep things moving
this.$object.addEventListener('transitionend', this.boundEvent);
// Start it moving
this._moveOnce();
this.is_running = true;
}
RandomObjectMover.prototype.stop = function() {
if (!this.is_running) {
return;
}
this.$object.removeEventListener('transitionend', this.boundEvent);
this.is_running = false;
}
// Init it
var x = new RandomObjectMover(document.querySelector(".circle"), window);
// Start it off
x.start();
.circle {
clip-path: circle(50%);
height: 40px;
width: 40px;
margin: 20px;
position: absolute;
}
I have modified the snippet which works as you expected.
There was a mistake where you were initializing and creating the object instance only once and none of the div elements that you created inside the setInterval function never got Instantiated.
I think you are just starting out with JavaScript with this sample project.
Below are few suggestions:
Learn to debug the code. You should be using dev tools by making use of debugger statement where it takes you to the source code to analyze the variable scope and stack during the runtime. console.log also helps in few situations.
I could see a lot of confusing naming convention (You have named the create div parameter as id but creating a div class using that id)
Try using ES6 features (class syntax is really good when writing OOP in JS although it's just a syntactic sugar for prototype)
//creating circles
var widthHeight = 40; // <-- circle width
var margin = 20; // <-- margin - is it necessary ?
var delta = widthHeight + margin;
function createAndInitializeDivObject(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = document.documentElement.clientHeight;
var documentWidth = document.documentElement.clientWidth;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.backgroundColor = color;
}
div.classList.add("circle");
div.classList.add("animation");
// Get the random positions minus the delta
currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;
// Keep the positions between -20px and the current positions
var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";
document.body.appendChild(div);
var x = new RandomObjectMover(document.querySelector(`.${id}`), window);
x.start();
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createAndInitializeDivObject(`circle${i}`)
}, oneSecond);
//move circles
function RandomObjectMover(obj, container) {
this.$object = obj;
this.$container = container;
this.container_is_window = container === window;
this.pixels_per_second = 250;
this.current_position = { x: 0, y: 0 };
this.is_running = false;
}
// Set the speed of movement in Pixels per Second.
RandomObjectMover.prototype.setSpeed = function(pxPerSec) {
this.pixels_per_second = pxPerSec;
}
RandomObjectMover.prototype._getContainerDimensions = function() {
if (this.$container === window) {
return { 'height' : this.$container.innerHeight, 'width' : this.$container.innerWidth };
} else {
return { 'height' : this.$container.clientHeight, 'width' : this.$container.clientWidth };
}
}
RandomObjectMover.prototype._generateNewPosition = function() {
// Get container dimensions minus div size
var containerSize = this._getContainerDimensions();
var availableHeight = containerSize.height - this.$object.clientHeight;
var availableWidth = containerSize.width - this.$object.clientHeight;
// Pick a random place in the space
var y = Math.floor(Math.random() * availableHeight);
var x = Math.floor(Math.random() * availableWidth);
return { x: x, y: y };
}
RandomObjectMover.prototype._calcDelta = function(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt( dx*dx + dy*dy );
return dist;
}
RandomObjectMover.prototype._moveOnce = function() {
// Pick a new spot on the page
var next = this._generateNewPosition();
// How far do we have to move?
var delta = this._calcDelta(this.current_position, next);
// Speed of this transition, rounded to 2DP
var speed = Math.round((delta / this.pixels_per_second) * 100) / 100;
//console.log(this.current_position, next, delta, speed);
this.$object.style.transition='transform '+speed+'s linear';
this.$object.style.transform='translate3d('+next.x+'px, '+next.y+'px, 0)';
// Save this new position ready for the next call.
this.current_position = next;
};
RandomObjectMover.prototype.start = function() {
if (this.is_running) {
return;
}
// Make sure our object has the right css set
this.$object.willChange = 'transform';
this.$object.pointerEvents = 'auto';
this.boundEvent = this._moveOnce.bind(this)
// Bind callback to keep things moving
this.$object.addEventListener('transitionend', this.boundEvent);
// Start it moving
this._moveOnce();
this.is_running = true;
}
RandomObjectMover.prototype.stop = function() {
if (!this.is_running) {
return;
}
this.$object.removeEventListener('transitionend', this.boundEvent);
this.is_running = false;
}
// Init it
var x = new RandomObjectMover(document.querySelector(".circle"), window);
// Start it off
x.start();
.circle {
width: 35px;
height: 35px;
border-radius: 35px;
background-color: #ffffff;
border: 3px solid purple;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="circle"></div>
<script src="app.js"></script>
</body>
</html>

I wanna repeat function infinite but i couldn't

I wanna do some effect to my background so i tought i can add some shapes flying around but i do only 1 shape i cant loop or anything
i tried call function more than a one time but it doesnt help
function animasyon(a) {
window.onload=function(){
var id = setInterval(anim,5);
$('body').append('<div class=shape></div>');
$('body').append('<div class=shape></div>');
var kutu = document.getElementsByClassName("shape");
var pos = 0;
var x = window.innerWidth;
var y = window.innerHeight;
var borderSize = Math.floor(Math.random() * 3 ) + 1;
var ySize = Math.floor(Math.random() * y ) + 1;
var Size = Math.floor(Math.random() * 30 ) + 5;
var yon = Math.floor(Math.random() *2)+1;
var dolu = Math.floor(Math.random() *2)+1;
if (ySize > 50) { ySize-=20; }
function anim(){
if (pos == x) {
clearInterval(id);
document.getElementById("shape").remove();
}else{
pos++;
kutu[a].style.position = "absolute";
kutu[a].style.border = "solid rgb(119,38,53) "+borderSize+"px";
kutu[a].style.left = pos+"px";
kutu[a].style.width = Size+"px";
kutu[a].style.height = Size+"px";
if (yon == 1) { ySize-=0.2; } else { ySize+=0.2; }
if (dolu==1) {kutu[a].style.background = "rgb(119,38,53)";}
if (kutu[a].offsetTop < 0 || kutu[a].offsetTop > y-30) {document.getElementById("shape").remove();}
kutu[a].style.top = ySize+"px";
}
}
}
}
animasyon(0);
Try Calling 'anim' function in this way
setInterval(function(){anim()},5);
Your problem is that you are assigning window.onload function a value inside the function animasyon
window.onload holds only 1 function. If you call animation function more than once, then the last one will overwrite the first one.
Edit: You need to separate your animation logic from the page load logic. They are completely separate things.
Here is an example of adding multiple objects and animating each separately.
// HTML
<div id="container">
<div id="ball"></div>
<div id="ball2"></div>
<div id="ball3"></div>
<div id="ball4"></div>
</div>
// CSS
#ball, #ball2, #ball3, #ball4 {
background: red;
border: 1px solid #FAFDFA;
display: inline-block;
width: 1em;
height: 1em;
border-radius: 2em;
position: absolute;
}
#ball2 {
background: blue;
}
#ball3 {
background: green;
}
#ball4 {
background: purple;
}
#container {
width: 512px;
height: 512px;
background: black;
position: relative;
}
// JS
const container = document.getElementById('container');
const stageWidth = 512;
const stageHeight = 512;
const makeFall = (elementId) => {
// this function makes an enlement fall in random direction
const animationSpeed = 4;
// your onload function
const ball = document.getElementById(elementId);
let directionX = (Math.random() * animationSpeed * 2) - animationSpeed;
let directionY = Math.random() * animationSpeed;
const setRandomStart = () => {
ball.style.top = '10px';
ball.style.left = (Math.random() * (stageWidth / 2)) + 'px';
directionX = (Math.random() * animationSpeed * 2) - animationSpeed;
directionY = Math.random() * animationSpeed;
}
setRandomStart();
let animationInterval = setInterval(() => {
let px = parseFloat(ball.style.left);
let py = parseFloat(ball.style.top);
px += directionX;
py += directionY;
if (px > stageWidth - 20 || py > stageHeight - 20 || px < -20) {
setRandomStart();
} else {
ball.style.left = px + 'px';
ball.style.top = py + 'px';
}
}, 48);
}
// In Your onload function you can add the elements and then animate
makeFall('ball');
makeFall('ball2');
makeFall('ball3');
makeFall('ball4');
https://jsfiddle.net/753oL8re/4/

jquery plugin, settimeout and div not being append, simple weird case

I'm writing a jquery plugin the code below is not working (I mean the setTimeout is working but nothing is append)
var self = this;
for (var i=0; i<=10; i++) {
setTimeout(function() {
self.append(bubble);
}, 1000);
}
And the code below is working:
for (var i=0; i<=10; i++) {
this.append(bubble);
}
this is a jquery selection. I really don't get what's going on. It can't be scope issue .. can it be ? I don't get it. Thanks in advance for you help
Edit: bubble is a simple div (" ")
Below the whole plugin code:
(function($) {
'use strict';
$.fn.randomBubble = function(options) {
var self = this;
var settings = $.extend({
color: 'blue',
backgroundColor: 'white',
maxBubbleSize: 100
}, options);
var frame = {
height: this.height(),
width: this.width(),
}
var bubble = "<div class='randomBubble'> </div>";
this.getLeft = function(width) {
var left = Math.random() * frame.width;
if (left > (frame.width / 2)) {
left -= width;
} else {
left += width;
}
return left
}
this.getTop = function(height) {
var top = Math.random() * frame.height;
if (top > (frame.height / 2)) {
top -= height;
} else {
top += height;
}
return top
}
this.removeBubbles = function() {
var currentBubbles = this.find('.randomBubble');
if (currentBubbles.length) {
currentBubbles.remove();
}
}
window.oh = this;
for (var i = 0; i <= 10; i++) {
var timer = Math.random() * 1000;
setTimeout(function() {
window.uh = self;
self.append(bubble);
console.log("oh");
}, 1000);
}
this.randomize = function() {
//self.removeBubbles();
var allBubbles = this.find('.randomBubble');
allBubbles.each(function(i, el) {
var height = Math.random() * settings.maxBubbleSize;
var width = height;
$(el).css({
color: settings.color,
backgroundColor: settings.backgroundColor,
zIndex: 1000,
position: 'absolute',
borderRadius: '50%',
top: self.getTop(height),
left: self.getLeft(width),
height: height,
width: width
});
});
}
this.randomize();
//var run = setInterval(self.randomize, 4000);
return this.find('.randomBubble');
}
})(jQuery);
Because the bubbles are appended later due to the setTimeout(), this selector in your randomize() function comes up empty:
var allBubbles = this.find('.randomBubble');
That is why appending them in a simple for loop works fine.
If you really want to use the setTimout() to append your bubbles, one option is to style them when you add them:
setTimeout(function() {
var height = Math.random() * settings.maxBubbleSize;
var width = height;
var b = $(bubble).css({
color: settings.color,
backgroundColor: settings.backgroundColor,
zIndex: 1000,
position: 'absolute',
borderRadius: '50%',
top: self.getTop(height),
left: self.getLeft(width) ,
height: height,
width: width
});
self.append(b);
}, 1000);
Fiddle
Is it because you still call randomize() right away, even when you postpone the creation for one second?
You will also return an empty selection in that case, for the same reason.
Also, you probably want to use the timer variable in setTimeout() instead of hardcoding all to 1000 ms?
this is a javascript selection, the selector in jquery is $(this)
$.fn.randomBubble = function(options) {
var self = $(this);
};

Javascript setTimeout, Loops and Closure

The following code has me confused. My goal is to fade an HTML element from one opacity level to another, over a period of time. Below is my dimScreen() method, used to create a darkened overlay and fade it in.
var overlay;
function dimScreen()
{
if(!overlay)
{
overlay = document.createElement('div');
overlay.setAttribute('id', 'overlay');
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.zindex = '1000';
overlay.style.background = '#000013';
overlay.style.position = 'fixed';
overlay.style.left = '0';
overlay.style.top = '0';
overlay.style.opacity = '.0';
document.body.appendChild(overlay);
fade('overlay', 0, 75, 200);
}
}
Here is my working fade function:
function fade(eID, startOpacity, stopOpacity, duration)
{
var speed = Math.round(duration / 100);
var timer = 0;
if (startOpacity < stopOpacity)
{ // fade in
for (var i=startOpacity; i<=stopOpacity; i++)
{
setTimeout("setOpacity('"+eID+"',"+i+")", timer * speed);
timer++;
} return;
}
for (var i=startOpacity; i>=stopOpacity; i--)
{ // fade out
setTimeout("setOpacity('"+eID+"',"+i+")", timer * speed);
timer++;
}
}
And my working setOpacity:
function setOpacity(eID, opacityLevel)
{
var eStyle = document.getElementById(eID).style;
eStyle.opacity = opacityLevel / 100;
eStyle.filter = 'alpha(opacity='+opacityLevel+')';
}
I would like to, however, change my fade() function to user a closure in the form of:
setTimeout(function(){setOpacity(eID,i)}, timer * speed);
I could then pass in the actual overlay div, instead of the id 'overlay'. When I do this, however, rather than animating a gradual fade-in of the overlay div, it just goes right to the last opacity value with no transition. Why does this happen?
I have a feeling this is something simple that I am missing because I've been looking at it for so long. Any help would be appreciated!
It's too late and still too hot to think much here right now. (2.30am, 28°C)
Forgive me if my explanation falls short of expectations.
Basically, because you construct text strings to pass to setTimeout, each call gets the correct value for i. Since to pass an actual element, you can't use the string trick, you end up using the same value of i for each call to setOpacity.
As your question title indicates you understand, you need to use closures to get it to work right. I can't find(only followed 2 or 3 links) a good tute/S.O question that explains it in a way that seems relevant and clear.
Hope the code will be of use.
var overlay;
function dimScreen()
{
if(!overlay)
{
overlay = document.createElement('div');
overlay.setAttribute('id', 'overlay');
overlay.style.width = '100%';
overlay.style.height = '100%';
overlay.style.zindex = '1000';
overlay.style.background = '#000013';
overlay.style.position = 'fixed';
overlay.style.left = '0';
overlay.style.top = '0';
overlay.style.opacity = '.0';
document.body.appendChild(overlay);
myFade(overlay, 0, 75, 2000);
}
}
function myFade(element, startOpacity, stopOpacity, duration)
{
var speed = Math.round(duration / 100);
var timer = 0;
if (startOpacity < stopOpacity)
{ // fade in
for (var i=startOpacity; i<=stopOpacity; i++)
{
(
function()
{
var myI = i;
setTimeout(function(){mySetOpacity(element,myI)}, timer * speed);
}
)()
timer++;
}
}
else
for (var i=startOpacity; i>=stopOpacity; i--)
{ // fade out
for (var i=startOpacity; i<=stopOpacity; i++)
{
(
function()
{
var myI = i;
setTimeout(function(){mySetOpacity(element,myI)}, timer * speed);
}
)()
timer++;
}
}
}
function mySetOpacity(el, opacityLevel)
{
var eStyle = el.style;
eStyle.opacity = opacityLevel / 100;
eStyle.filter = 'alpha(opacity='+opacityLevel+')';
}

JavaScript Div Expanding

I hope someone can help me with this.
When my HTML Textbox is clicked, I would like a Div to expand in length using preferably only JavaScript. I attached a picture to show in more depth. Again, If anyone could help me - I'll be greatfull.
Something like this should be sufficient, HTML:
<input type = "text" style = "width: 500px;" onfocus = "expand();" onblur = "collapse();">
<div id = "yourdiv"></div>
CSS:
#yourdiv {
margin-top: 0px;
background-color: rgb(0, 162, 232);
width: 500px;
height: 0px;
}
JavaScript:
var t;
function expand() {
var dv = document.getElementById("yourdiv");
var duration = 500; //number of milliseconds for animation; 1000ms = 1s.
var stepDur = Math.floor(duration / 200); //200px is our goal height here
var curHeight = parseInt(dv.style.height.substr(0, dv.style.height.length - 2), 10); //current height of dv
if(isNaN(curHeight)) {
curHeight = 0;
}
clearTimeout(t); //make sure no other animation is happening
function doAnim() {
if(curHeight >= 200) {
//we're done!
return;
}
curHeight ++;
dv.style.height = curHeight + "px";
t = setTimeout(doAnim, stepDur);
}
doAnim();
}
function collapse() {
var dv = document.getElementById("yourdiv");
var duration = 500; //number of milliseconds for animation; 1000ms = 1s.
var stepDur = Math.floor(duration / 200);
var curHeight = parseInt(dv.style.height.substr(0, dv.style.height.length - 2), 10); //current height of dv
clearTimeout(t); //make sure no other animation is happening
function doAnim() {
if(curHeight <= 0) {
//we're done!
return;
}
curHeight --;
dv.style.height = curHeight + "px";
t = setTimeout(doAnim, stepDur);
}
doAnim();
}
Demo: little link.
I hope that helped!

Categories