Creating a class based JS instead of id - javascript

So I have created this javascript that animates a certain place using it's ID.
The problem is that there are many of those on the site and meaning this I'd have to duplicate this function a lot of times just to replace the x in getElementById("x").
So here is the code I fully done by myself:
var popcount = 0;
var opanumber = 1;
var poptimeout;
function pop() {
if (popcount < 10) {
popcount++;
if (opanumber == 1) {
document.getElementById("nav1").style.opacity = 0;
opanumber = 0;
poptimeout = setTimeout("pop()", 50);
}
else {
document.getElementById("nav1").style.opacity = 1;
opanumber = 1;
poptimeout = setTimeout("pop()", 50);
}
}
else {
popcount = 0;
document.getElementById("nav1").style.opacity = 1;
}
}
function stoppop() {
clearTimeout(poptimeout);
popcount = 0;
document.getElementById("nav1").style.opacity = 1;
}
I would gladly appreciate any information on how I could solve this situation and also any tutorials about using classes and "this".

Something like this; rather than hard code a value into a function it is better to pass the value in so you can reuse the function on more than one thing. In this case you can now call startPop and stopPop with the name of a CSS class.
var popTimeout;
function setOpacity(className, value) {
Array.prototype.forEach.call(
document.getElementsByClassName(className),
function(el) {
el.style.opacity = value;
}
);
}
function pop(className, popCount, opaNumber) {
if (popCount < 10) { //Must be even number so you end on opacity = 1
setOpacity(className, opaNumber);
popTimeout = setTimeout(function() {
pop(className, popCount++, 1-opaNumber);
}, 50);
}
}
function startPop(className) {
pop(className, 0, 0);
}
function stopPop(className) {
clearTimeout(popTimeout);
setOpacity(className, 1);
}
In case you are wondering about the 1 - opaNumber; this is a simpler way of switching a value between 1 and 0. As 1-1=0 and 1-0=1.

Well you started out with recognizing where you have the problem and that's already a good thing :)
To make your code a bit more compact, and get as many things as possible out of the local scope, you could check the following implementation.
It is in a sense a small demo, where I tried adding as much comments as possible.
I edited a bit more after realizing you rather want to use classnames instead of id's :) As a result, I am now rather using the document.querySelectorAll that gives you a bit more freedom.
Now you can call the startPop function with any valid selector. If you want to pop purely on ID, you can use:
startPop('#elementId');
or if you want to go for classes
startPop('.className');
The example itself also add's another function, nl trigger, that shows how you can start / stop the functions.
I also opted to rather use the setInterval method instead of the setTimeout method. Both callback a function after a certain amount of milliseconds, however setInterval you only have to call once.
As an extra change, stopPop also now uses the document.querySelectorAll so you have the same freedom in calling it as the startPop function.
I added 2 more optional parameters in the startPop function, namely total and callback.
Total indicates the maximum times you wish to "blink" the element(s), and the callback provides you with a way to get notified when the popping is over (eg: to update potential elements that started the popping)
I changed it a bit more to allow you to use it for hovering over an element by using the this syntax for inline javascript
'use strict';
function getElements( className ) {
// if it is a string, assume it's a selector like #id or .className
// if not, assume it's an element
return typeof className === "string" ? document.querySelectorAll( className ) : [className];
}
function startPop(className, total, callback) {
// get the element once, and asign a value
var elements = getElements( className ),
current = 0;
var interval = setInterval(function() {
var opacity = ++current % 2;
// (increase current and set style to the left over part after dividing by 2)
elements.forEach(function(elem) { elem.style.opacity = opacity } );
// check if the current value is larger than the total or 10 as a fallback
if (current > (total || 10)) {
// stops the current interval
stopPop(interval, className);
// notifies that the popping is finished (if you add a callback function)
callback && callback();
}
}, 50);
// return the interval so it can be saved and removed at a later time
return interval;
}
function stopPop(interval, className) {
// clear the interval
clearInterval(interval);
// set the opacity to 1 just to be sure ;)
getElements( className ).forEach(function(elem) {
elem.style.opacity = 1;
});
}
function trigger(eventSource, className, maximum) {
// get the source of the click event ( the clicked button )
var source = eventSource.target;
// in case the attribute is there
if (!source.getAttribute('current-interval')) {
// start it & save the current interval
source.setAttribute('current-interval', startPop(className, maximum, function() {
// completed popping ( set the text correct and remove the interval )
source.removeAttribute('current-interval');
source.innerText = 'Start ' + source.innerText.split(' ')[1];
}));
// change the text of the button
source.innerText = 'Stop ' + source.innerText.split(' ')[1];
} else {
// stop it
stopPop(source.getAttribute('current-interval'), className);
// remove the current interval
source.removeAttribute('current-interval');
// reset the text of the button
source.innerText = 'Start ' + source.innerText.split(' ')[1];
}
}
<div class="nav1">
test navigation
</div>
<div class="nav2">
Second nav
</div>
<div class="nav1">
second test navigation
</div>
<div class="nav2">
Second second nav
</div>
<a id="navigation-element-1"
onmouseover="this.interval = startPop( this )"
onmouseout="stopPop( this.interval, this )">Hover me to blink</a>
<button type="button" onclick="trigger( event, '.nav1', 100)">
Start nav1
</button>
<button type="button" onclick="trigger( event, '.nav2', 100)">
Start nav2
</button>

If you do want to take it back to using IDs, then you will need to think about popTimeout if you run this on more than one element at a time.
function setOpacity(id, value) {
document.getElementById(id).style.opacity = value;
}
function runPop(id) {
function pop(id, popCount, opaNumber) {
if (popCount < 10) { //Must be even number so you end on opacity = 1
setOpacity(id, opaNumber);
popTimeout = setTimeout(function() {
pop(id, popCount++, 1-opaNumber);
}, 50);
}
}
var popTimeout;
pop(id, 0, 0);
return function() {
clearTimeout(popTimeout);
setOpacity(id, 1);
}
}
var killPop = [];
function startPop(id) {
killPop[id] = runPop(id);
}
function stopPop(id) {
killPop[id]();
}

Related

javascript value is not updating after onmousevent

I use 1 span tag at the moment.
<span onmouseover="numberOne()" onclick="imgNumber(); return false" onmouseout="noHoverOne()" class="img1 img" id="new-img"> </span>
The span has a "deafult" image, when the mouse goes on the span, another image will be shown, when the mouse leaves the span, the default image will be shown again.
now the javascript:
function numberOne() {
var random2 = Math.floor((Math.random() * 3) + 1);
var random3 = Math.floor((Math.random() * 3) + 1);
do {
var random = Math.floor((Math.random() * 3) + 1);
} while (random === numberOne.last);
numberOne.last = random;
Random numbers are made here. So every time you leave the span and go on the span, there will be a different image.
if (random == 2) {
document.getElementById('new-img').style = "background-image: url('http://web-stars.nl/molgeld.jpg');";
} else if ((random==random2)==random3) {
document.getElementById('new-img').style = "background-image: url('http://web-stars.nl/vrijstelling.jpg');";
} else {
document.getElementById('new-img').style = "background-image: url('http://web-stars.nl/haspel.jpg');";
}
These are the images that will be shown depending on the number
return random;
}
var value = numberOne();
function imgNumber() {
document.getElementById('demo').innerHTML = value;
}
imgNumber();
This is where I am stuck. Before I even have touched the span tag with my mouse, there is already a random number and when I go with the mouse on the span tag, it shows a different image but not a different number. I want to use this number somehow to create a new level for my game. The game is influenced by the chosen image.
So there is a lot going on and it's pretty messy. So please, I would love to hear any kind of constructive feedback.
[EDIT] I will keep the JSfiddle up to date, but there is an error in the preview, it won't display anything. It's still useful Jsfiddle
use a wrapper function where you can call both imgNumber and numberOne
function mouseHover() {
var value = numberOne()
imgNumber(value)
}
function imgNumber(value) {
document.getElementById('demo').innerHTML = value;
}
<span onmouseover="mouseHover()" onclick="imgNumber(); return false" onmouseout="noHoverOne()" class="img1 img" id="new-img"> </span>
Your code is a bit illogical. It seems you want to randomly assign an image to an element background and get a different element each time. So put the image URLs in an array and randomly grab one, ensuring it's different to the last. This means you can add or reduce the images you want to display just by modifying the images array.
Also put all your data in an object rather than using globals, it's just neater. And give your functions names that tell you what they do.
E.g.
var imageData = {
pix: ['http://web-stars.nl/molgeld.jpg',
'http://web-stars.nl/vrijstelling.jpg',
'http://web-stars.nl/haspel.jpg'
],
random: null
}
function changeImage(el) {
// limit do loop just in case data is bad
// Infinite loops are bad...
var len = imageData.pix.length;
var i = len;
do {
var random = Math.random() * len | 0;
} while (i-- && imageData.random == random)
imageData.random = random;
el.style.backgroundImage = imageData.pix[random];
console.log(random, imageData.pix[random]);
}
function updateImageRef() {
document.getElementById('imageRef').textContent = imageData.random;
}
<div id="imageDiv" onmouseover="changeImage(this)" onclick="updateImageRef()">Image div</div>
<div id="imageRef"><div>

JavaScript Countdown with argument passing in

You are given an integer called start_num. Write a code that will countdown from start_num to 1, and when the countdown is finished, will print out "Liftoff!".
I am unsure how to do this and keep getting stuck.
This is the code I am provided with at the beginning of the problem:
function liftoff_countdown(start_num) {
// My code goes here!
}
And then they want me to pass in a value such as the 5:
liftoff_countdown(5);
And then this will be my output:
6
5
4
3
2
1
"Liftoff!"
Thanks!
Look at this maybe help you to create your own code
make two file in a same folder (script.js and index.html)
index.html
<!doctype html>
<head>
<title>Countdown</title>
</head>
<body>
<div id="container">
<div id="inputArea">
</div>
<h1 id="time">0</h1>
</div>
<script src="script.js"></script>
</body>
</html>
script.js
var valueRemaining;
var intervalHandle;
function resetPage() {
document.getElementById("inputArea").style.display = "block";
}
function tick() {
var valueDisplay = document.getElementById("time");
valueDisplay.innerHTML = valueRemaining;
if (valueRemaining === 0) {
valueDisplay.innerHTML = "Liftoff!";
clearInterval(intervalHandle);
resetPage();
}
valueRemaining--;
}
function startCountdown() {
var count = document.getElementById("count").value;
if (isNaN(count)) {
alert("Please enter a number!");
return;
}
valueRemaining = count;
intervalHandle = setInterval(tick, 1000);
document.getElementById("inputArea").style.display = "none";
}
// as soon as the page is loaded...
window.onload = function () {
var inputValue = document.createElement("input");
inputValue.setAttribute("id", "count");
inputValue.setAttribute("type", "text");
// create a button
var startButton = document.createElement("input");
startButton.setAttribute("type", "button");
startButton.setAttribute("value", "Start Countdown");
startButton.onclick = function () {
startCountdown();
};
// add to the DOM, to the div called "inputArea"
document.getElementById("inputArea").appendChild(inputValue);
document.getElementById("inputArea").appendChild(startButton);
};
in this example you have many things to understand how javascript works behind scenes.
How about this...
function liftoff_countdown()
{
var span=document.getElementById('num');
var i=document.getElementById('num').innerText;
i=i-1;
span.innerText=i;
if (i==0){
span.innerText='Liftoff!';
clearInterval(count_down)
}
}
var count_down=setInterval(liftoff_countdown,1000);
<span id="num">5</span>
You can achieve this with a simple recursive function and the use of setTimeout to recursively call the function after a time lapse of 1 second.
function lift_off(seconds) {
if(seconds == 0) {
console.log('liftoff');
} else {
console.log(seconds--);
setTimeout(function(){lift_off(seconds);},1000);
}
}
lift_off(10);
Here is a working JSFiddle
Preface
A lot of these answers seem to be focused on doing things with timers and recursion. I do not believe that is your intent. If your only goal is to print those values to the console, you could simply do the following (see the comments for an explanation).
The Answer
function liftoff_countdown(start_num) {
// Loops through all values between 0 and start_num
for(int i = 0; i < start_num; i++) {
// Prints the appropriate value by subtracting from start_num
console.log( start_num - i );
}
// Upon exiting the loop, prints "Liftoff!"
console.log("Liftoff!");
}
Additional Thoughts
You could just as easily loop backwards through the numbers instead of forward like so:
for(int i = start_num; i > 0; i--){
console.log( i );
}
I tend to lean towards iterating forwards just because it's more common, and it's often easy to confuse readers of your code if they gloss over the loop initialization.
Additionally, I am working with the assumption that when you say "print" you mean "console.log()". If this is untrue, you could of course use any other function in its place (e.g. alert( "Liftoff!" );).

NaN return value from function Javascript || Function Execution Order

Newbie in Javascript here, and after hours digging trough other questions I'm not quite sure how to explain this to be honest, but i'll give it my best, hopefully you'll be able to help me.
HTML:
<div id='header'> <h1> Pastel Land </h1> </div>
<div id='container'>
<div id='readyContainer'>
<h3> This game will start in </h3>
<h1 id='readySeconds'> </h1>
</div>
<div id='shape'> </div>
</div>
<div id='features'>
<button id='start'> START </button>
<button id='stop'> STOP </button>
<p id='timeBox'></p>
<p id='timeAverageBox'></p>
</div>
<div id='testbox'> </div>
FULL SCRIPT:
document.getElementById('start').onclick = function () {
document.getElementById('readyContainer').style.display = 'block';
document.getElementById('readySeconds').innerHTML = '3'
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '2'}, 1000);
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '1'}, 2000);
setTimeout(readyAlert,3000);
setTimeout(displayShape, 3000);
var style = document.getElementById('shape').style;
var el = document.getElementById('shape');
el.addEventListener("click", a, false);
el.addEventListener("click", b, false);
function a() {
style.display = "none";
displayShapeDelay(); // calls the delay function
}
function b() {
end = new Date().getTime(); // saves time when clicked
var time = (end - start)/1000 ; // calculates interval from shape creation until click
document.getElementById('timeBox').innerHTML = time + 's';
return time;
}
document.getElementById('testbox').innerHTML = b();
function readyAlert() {
document.getElementById('readyContainer').style.display = 'none';
}
function getRandomColor() {
var hex = ["#96ceb4", "#ffeead", "#ff6f69", "#ffcc5c", "#88db8b0", "#528491"];
var color = hex[Math.floor(Math.random() * 6)]; // generates integer numbers [0,5], selects indexed item from hex
return color;
}
function displayShape () {
var percentages = [];
for (var i=0; i<4; i++){ // generates a list with 4 different random integer values [5,60]
percentages.push((Math.floor(Math.random() * 61) + 5));
}
var width = (Math.floor(Math.random() * 61) + 5); // generates integer numbers [5,60]
var shapeRand = Math.random()
if (shapeRand < 0.3) { // circle
style.borderRadius = "50%";
} else if (shapeRand >= 0.3 && shapeRand < 0.6) { // random shape
style.borderTopLeftRadius = percentages[0] + "%";
style.borderBottomRightRadius = percentages[1] + "%";
style.borderTopRightRadius = percentages[2] + "%";
style.borderBottomLeftRadius = percentages[3] + "%";
} else { // square
style.borderRadius = "0%";
}
//general shape styles
style.width = width + "%";
style.height = width + "%";
style.display = "block";
style.backgroundColor = getRandomColor();
style.top = percentages[0] + "%";
style.left = percentages[3] + "%";
start = new Date().getTime(); // saves time when shape is created
console.log(width);
console.log(getRandomColor());
console.log(shapeRand);
console.log(percentages);
}
function displayShapeDelay () { // calls the main function with a delay between ]0s,2s[
setTimeout(displayShape, Math.random() * 2000);
}
document.getElementById('stop').onclick = function() {
}
}
Before I had this:
My goal was to return var 'time' to the global scope, so that I could use it to create an array of each value created with each click. I've realised that this was not possible from an anonymous function.
document.getElementById('shape').onclick = function() { // calls the delay function
style.display = "none";
displayShapeDelay();
end = new Date().getTime();
time = (end - start)/1000 ;
document.getElementById('timeBox').innerHTML = time + 's';
return time
}
So this is the code I have now :
var shapeClick = document.getElementById('shape');
shapeClick.addEventListener("click", a, false);
shapeClick.addEventListener("click", b, false);
function a() {
style.display = "none";
displayShapeDelay(); // calls the delay function
}
function b() {
end = new Date().getTime(); // saves time when clicked
var time = (end - start)/1000 ; // calculates interval from shape creation until click
document.getElementById('timeBox').innerHTML = time + 's';
return time;
}
document.getElementById('testbox').innerHTML = b();
Now, there's a couple of issues with this:
1- I can't seem to understand why the two "time divs" are assigned values after pressing the Start button. This means that function b is running, but shouldn't it only be running after the onClick event?
2- In the 'first-round' I understand why both values show up as NaN, since there's no value assigned to the variable "time" yet. But after the onClick event executes, the 'time' value assigned inside 'timeBox' works fine, but the one called outside the function doesn't. Isn't "return time" inside function b, supposed to be returning the value of the "time" variable?
Thanks in advance!
Pastel Land
The onclick function is serving as the outer function of a whole lot of code which execute when the start button is clicked. Also all of it runs every time the start button is clicked: click start multiple times quickly to see a problem. .
Inside #start.onclick() you have
document.getElementById('testbox').innerHTML = b();
in mainline click handler code: it is not inside another function and runs when the start button is clicked. Since end has not been set yet, the result for time is NaN. The code inside function b set the content of #timebox as well.
If you run the code in strict mode the javascript engine will tell you that end has not been declared. It should be - even if requred in global scope.
As an aside, fyi, Date.now() avoids the need to create and discard a Date object and is equivalent to new Date().getTime().
I suggest reworking the code to move the logic of Pastel Land outside the start button click handler, and have the click handler call into the main application code as needed but only contain logic specific to the start action itself. If you want to avoid polluting global scope you can include all the code in an IIFE (immediately invoked function expression) that would serve the same scope containment provision that the click handler is currently providing. Kindly, I think the code in its current state is presenting an x-y problem :-)
The Game
A restructured version of Pastel Land is shown below for several reasons: you've had time to try it yourself, most of the code is yours and the remainder demonstrates what was meant by the suggestion. And it's a very silly game that deserves to be played!
<!DOCTYPE html>
<html>
<head>
<title>PastelLand</title>
<meta charset="utf-8">
<script>
window.addEventListener("load", function() // an IIFE
{"use strict"
// Pastel Land
var running = false;
var start = 0;
var end = 0;
var times = []; // calculating average still to do
var el, style;
function getRandomColor() {
var hex = ["#96ceb4", "#ffeead", "#ff6f69", "#ffcc5c", "#88db8b0", "#528491"];
var color = hex[Math.floor(Math.random() * 6)]; // generates integer numbers [0,5], selects indexed item from hex
return color;
}
function displayShape () {
var percentages = [];
for (var i=0; i<4; i++){ // generates a list with 4 different random integer values [5,60]
percentages.push((Math.floor(Math.random() * 61) + 5));
}
var width = (Math.floor(Math.random() * 61) + 5); // generates integer numbers [5,60]
var shapeRand = Math.random()
if (shapeRand < 0.3) { // circle
style.borderRadius = "50%";
} else if (shapeRand >= 0.3 && shapeRand < 0.6) { // random shape
style.borderTopLeftRadius = percentages[0] + "%";
style.borderBottomRightRadius = percentages[1] + "%";
style.borderTopRightRadius = percentages[2] + "%";
style.borderBottomLeftRadius = percentages[3] + "%";
} else { // square
style.borderRadius = "0%";
}
//general shape styles
style.width = width + "px";
style.height = width + "px";
style.position = "absolute"
style.display = "block";
style.backgroundColor = getRandomColor();
style.top = percentages[0] + "%";
style.left = percentages[3] + "%";
start = Date.now(); // saves time when shape is created
console.log(width);
console.log(getRandomColor());
console.log(shapeRand);
console.log(percentages);
}
function displayShapeDelay () { // calls the main function with a delay between ]0s,2s[
setTimeout(displayShape, Math.random() * 2000);
}
function readyAlert() {
document.getElementById('readyContainer').style.display = 'none';
}
function userFound() {
style.display = "none";
end = Date.now();
var time = (end - start)/1000 ; // calculates interval from shape creation until click
document.getElementById('timeBox').innerHTML = time + 's';
displayShapeDelay(); // calls the delay function
times.push( time); // saves time user took to find shape
}
function userStart() {
if( running)
return;
running = true;
document.getElementById('readyContainer').style.display = 'block';
document.getElementById('readySeconds').innerHTML = '3'
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '2'}, 1000);
setTimeout(function() {document.getElementById('readySeconds').innerHTML = '1'}, 2000);
setTimeout(readyAlert,3000);
setTimeout(displayShape, 3000);
times.length = 0; // reset times array
}
function userStop() {
running = false;
style.display="none"
}
function init() {
el = document.getElementById('shape');
style = el.style;
el.addEventListener("click", userFound, false);
document.getElementById('start').onclick=userStart;
document.getElementById('stop').onclick=userStop;
}
return init; // window load listener
}());
</script>
</head>
<body>
<div id='header'> <h1> Pastel Land </h1> </div>
<div id='container'>
<div id='readyContainer'>
<h3> This game will start in </h3>
<h1 id='readySeconds'> </h1>
</div>
<div id='shape' style="height:40px;width:40px;"></div>
</div>
<div id='features'>
<button id='start'> START </button>
<button id='stop'> STOP </button>
<p id='timeBox'></p>
<p id='timeAverageBox'></p>
</div>
<div id='testbox'> </div>
</body>
</html>
Calculation and display of averages and minor changes to page presentation remain to be done (I'm not coding them!). Units for width and height were changed from "%" to "px" (pixels) and "position: absolute;" added to shape.style. Functions a and b were combined into function userFound. Code involving "testbox" was omitted. The IIEF returns an initialization function to be executed after window load.
Notes
userStart and userStop click event handlers were defined using named function declarations instead of coding them as anonymous functions in the parameter lists of calls to other functions.
Declared function names refer to the function object created by their declaration. Hence setting the value of an element's onclick attribute to a function name works because the attribute requires a function object value. Setting onclick to the undefined value returned from calling one of the handlers would not work.
The start/stop handlers could have been registered as "click" event listeners, using addEventListener instead of element onclick values.
The init function is not called by the IIFE. The IIFE itself is called when the
window.addEventListener("load", function() { // IIFE code }() );
statement is executed in the head section of the page. All function objects declared at top level within the IIFE are created at this time. The function returned by the IIFE, init, is registered as a listener for later execution, after all DOM elements have been created for the HTML body and the window load event fires.
If you call userStart from init after other el and style have been initialized, the game will start. Although userStart is normally called in response to clicking the start button, it will still behave the same if called by other means.

create simple rotation with pause

How can I cycle through a series of elements, adding a class, pausing then removing the class and moving on to the next element. I have tried setInterval and I have tried setTimeout, but cannot seem to get it to work.
My Javascript
var numpromos = $('.promoteBlock').length;
var promonum = 1;
while (numpromos > promonum){
setInterval(function() {
$('#promoteCont .promoteBlock').fadeOut().removeClass('active');
$('#promoteCont #promo'+promonum).addClass('active');
}
}, 3000);
promonum++;
}
My HTML
<div id="promoteCont">
<div id="promo1" class="promoteBlock">Promotion No.1</div>
<div id="promo2" class="promoteBlock">Second Promo</div>
<div id="promo3" class="promoteBlock">Another one</div>
</div>
function playNext(){
console.log("playNext");
var active = $('#promoteCont').find(".promoteBlock.active");
if( active.length == 0 )
active = $(".promoteBlock:eq(0)");
var fout = active.next();
if( fout.length == 0 )
fout = $(".promoteBlock:eq(0)");
active.fadeOut().removeClass('active');
fout.fadeIn().addClass('active');
setTimeout(function(){
playNext();
},3000);
}
setTimeout(function(){
playNext();
},3000);
http://jsfiddle.net/p1c3kzj7/
Take things out of the while loop. You only need to set the interval once. Perform your state calculation (which item is selected) within the callback method itself. See below, which I believe is what your looking for.
// Global variables to maintain state... I'm sure I'll get some comments about these :p
var numpromos = $('.promoteBlock').length;
var promonum = 1;
$document.ready(function()
{
setInterval(function() {
$('#promoteCont .promoteBlock').fadeOut().removeClass('active');
$('#promoteCont #promo'+promonum).addClass('active');
promonum++;
if(promonums > numpromos)
promonum = 1;
}, 3000);
});

setInterval() not working after clearInterval() in this Javascript code

I have been ripping my hair off a couple of nights now with this problem:
I'm trying to create an expanding div with JavaScript. Here's the part of the HTML file:
<div id="bbc_div" class="bbc_div" style="display:none; height:200px;">
<input type="button" value="Show BBC" id="bbc_button" onclick="onclickBBC('bbc_div')" />
And here's the magical non-working JavaScript file:
var maxHeight = 100;
var curHeight = 1;
var wait = 5;
var timerID = new Array();
function onclickBBC(obj) {
if (document.getElementById(obj).style.display == "none") {
slideDown(obj);
}
else {
document.getElementById(obj).style.display="none"
}
}
function slideDown(obj) {
document.getElementById(obj).style.height="1px";
document.getElementById(obj).style.display="block";
timerID[obj] = setInterval("slideDownExec(\"" + obj + "\")", wait);
return;
}
function slideDownExec(obj) {
if (curHeight <= maxHeight) {
curHeight++;
document.getElementById(obj).style.height=curHeight + "px";
}
else {
endSlide(obj);
}
return;
}
function endSlide(obj) {
clearInterval(timerID[obj]);
return;
}
When I reload the page, div expands once to its right height. But, if I push the button without reloading page again after it has hided again, it doesn't work. display:block; works, but setInterval() isn't starting. So this happens after clearInterval() has executed. Why is clearInterval() killing my setInterval() permanently?
The timer is running, you just need to reset a variable:
function slideDown(obj)
{
document.getElementById(obj).style.height = "1px";
curHeight = 1;
I would use jQuery for this, it's a LOT easier.
You have an issue with curHeight not being set to 1 at the top of slideDown. If this doesn't happen, the if statement at the top of slideDownExec will only work the first time.
Additionally, does JavaScript allow non-integer array indexes?
> a['i'] = 4
4
> a
[]
> a['i']
4
What you're actually doing is adding a property called i to the array object. You might as well use an empty object rather than an array.

Categories

Resources