Understanding Functions and the semantics - javascript

Okay, Please be gentle I am learning Javascript.
I have two buttons (HTML5 <button> tags) they are both set to call the same function, In that function is two other functions (show + hide), Now, I am wondering if this is correct, i.e If i click on button hide, it calls function visibility, which then calls the function hide and hides everything defined in this function, including the original buttons. But if i click on button show, it hides the original content and displays extra content, with more buttons.(clickable process throughout)Or is it possible to call these functions separately within this function, For example:
function visible() {
function show() {
slide = document.getElementById('side');
pos = 0;
move = setInterval(slider, 1000/60);
slide1 = document.getElementById('main');
pos1 = 100;
move1 = setInterval(slider1, 1000/60);
document.getElementById('welcomer').style.display = 'none';
document.getElementById('welcome').style.display = 'none';
function slider() {
if (pos == 20) {
clearInterval(move);
}else {
pos++;
slide.style.display = 'block';
slide.style.width = pos + '%';
}
}
function slider1() {
if (pos1 == 80) {
clearInterval(move1);
}else {
pos1--;
slide1.style.width = pos1 + '%';
}
}
}
function hide() {
slide = document.getElementById('side');
pos = 0;
move = setInterval(slider, 1000/60);
slide1 = document.getElementById('main');
pos1 = 100;
move1 = setInterval(slider1, 1000/60);
document.getElementById('welcomer').style.display = 'none';
document.getElementById('welcome').style.display = 'none';
function slider() {
if (pos == 20) {
clearInterval(move);
}else {
pos++;
slide.style.display = 'block';
slide.style.width = pos + '%';
}
}
function slider1() {
if (pos1 == 80) {
clearInterval(move1);
}else {
pos1--;
slide1.style.width = pos1 + '%';
}
}
}
document.getElementById('vis').addEventListener('click', show());
document.getElementById('invis').addEventListener('click', hide());
}
Or is it semantically correct not to have nested functions, Instead to have the two separate functions, and call the functions separately onclick. For example:
function show() {
slide = document.getElementById('side');
pos = 0;
move = setInterval(slider, 1000/60);
slide1 = document.getElementById('main');
pos1 = 100;
move1 = setInterval(slider1, 1000/60);
document.getElementById('welcomer').style.display = 'none';
document.getElementById('welcome').style.display = 'none';
function slider() {
if (pos == 20) {
clearInterval(move);
}else {
pos++;
slide.style.display = 'block';
slide.style.width = pos + '%';
}
}
function slider1() {
if (pos1 == 80) {
clearInterval(move1);
}else {
pos1--;
slide1.style.width = pos1 + '%';
}
}
}
function hide() {
slide = document.getElementById('side');
pos = 0;
move = setInterval(slider, 1000/60);
slide1 = document.getElementById('main');
pos1 = 100;
move1 = setInterval(slider1, 1000/60);
document.getElementById('welcomer').style.display = 'none';
document.getElementById('welcome').style.display = 'none';
function slider() {
if (pos == 20) {
clearInterval(move);
}else {
pos++;
slide.style.display = 'block';
slide.style.width = pos + '%';
}
}
function slider1() {
if (pos1 == 80) {
clearInterval(move1);
}else {
pos1--;
slide1.style.width = pos1 + '%';
}
}
}
Or is it possible, for the button hide, do i just create an array, with every ID/Class Element i want to hide, call it with the onclick on the button to hide and then change the style to display: none; for all elements in that array?.
And vice versa for the divs i would create with button show?
Now i understand alot of this can be deemed opinionated, So the reason i am asking is this: I want to know which would be the quickest method using vanilla javascript, which way would shorten the amount of code and reduce loading time, with the best possible outcome based on facts.
Please note I have had to write this code with pretty much zero knowledge as i am learning Javascript, These are primarily for example, and both show/hide do the exact same thing for now, ultimately the show function will create more divs and content etc.

Having nested functions is perfectly acceptable, and often desirable or even necessary. The syntax would be as follows for doing so :
function base_function(){
this.function_1 = function(){};
this.function_2 = function(){};
}
This defines a function constructor with two values... function_1 and function_2. You could then call either of them using the following
var base = new base_function();
base.function_1();
Now, if you only need to reference those child functions within the scope of the base_function, something like the following would suffice.
function base_function(){
function child_function_1(){}
function child_function_2(){child_function_1();}
}
Think of function as it is in js, a datatype, like a string or numeric type. You can pass it to variables, reference it later on in code, pass it as a callback (like in setTimeout, you pass the reference to the function as a varaible. i.e. setTimeout(function_1,1000) rather than setTimeout(function_1(),1000)). You can also declare functions using var function_1 = function(){} because of this (and is my preferred method).
Because of the way javascript handles functions, you can do some interesting and super cool stuff with them - such as closures or IIFYs! Here is a great explanation of these and how to use them!
To answer your question, I would suggest going with the first route, while retaining a variable inside the function referencing the content you want to display/hide. Even if it means you need to write a few extra lines, it makes the code much more readable when you keep things modular, and readability really is king in most circumstances.
Something like this
var Vis_Controller = function(content){
this.content = content;
this.hide = function(){
content.style.display = "none";
}
this.show = function(){
content.style.display = "block";
}
}
window.addEventListener("load", function(){
var content = document.getElementById("content");
var button_show = document.getElementById("button-show");
var button_hide = document.getElementById("button-hide");
var vis_controller = new Vis_Controller(content);
button_show.addEventListener("click",vis_controller.show);
button_show.addEventListener("click",vis_controller.hide);
});

Related

can i use again a function that wraps setInterval and clearInterval statements?

i have a following function:
const catchingEggs = () => {
let eggIndex;
document.querySelector('html').style.backgroundColor = 'transparent';
leftArrow.style.display = 'none';
rightArrow.style.display = 'none';
player.removeEventListener('click', catchingEggs);
leftArrow.removeEventListener('click', choosePlayerLeft);
rightArrow.removeEventListener('click', choosePlayerRight);
document.querySelector('html').requestFullscreen();
myInterval = setInterval(function(){
if(score % 10 === 0) {
speed -= 10;
intervalScore += 5
}
if(heartIndex < 0) {
clearInterval(myInterval);
return;
}
eggIndex = Math.floor(Math.random()*4);
fallingEggs(allEggs[eggIndex], speed);
}, intervalLength);
}
which works fine, but if i want to keep reusing this function after clearInterval happened, by adding another catchingEggs() to the main function:
const playGame = () => {
screen.orientation.lock('landscape');
document.querySelector('html').style.backgroundColor = 'rgb(31, 28, 28)';
playerImages[0].style.display = 'block';
player.addEventListener('click', catchingEggs);
rightArrow.addEventListener('click', choosePlayerRight);
leftArrow.addEventListener('click', choosePlayerLeft);
}
to execute after a conditional, it doesn't do anything. Ideally i'd like to be able to change intervalLength while inside the interval, but that doesn't seem to be possible, so at least i want to be able to go around it by initiating the whole thing again, for example when score >= 20, so i added a new variable when true, as a condition of clearInterval (so far so good), and then inside playGame(): if new variable true catchingEggs(), but nothing happened.
thanks in advance.

JavaScript image fade out and in (using only JavaScript, no jQuery)

I am trying to make an image to fade out and then in. The problem is that when I use two functions, the image doesn't fade out but it immediately disappears. Is there anyone with amazing JavaScript skills to solve my problem?
Please do not tell me about jQuery because I already know how to do it using it, I only need to improve my JavaScript skills.
PS: I need also to understand why it doesn't work and how to make it work with as much details please.
Here is my code:
var el = document.getElementById("img1");
el.addEventListener("click", function() {
function fadeOut() {
el.style.opacity = 1;
function fade(){
var val = el.style.opacity;
if ((val -= .01) > 0){
el.style.opacity = val;
requestAnimationFrame(fade);
}
}
fade();
};
function fadeIn() {
el.style.opacity = 0;
function fade1() {
var val = el.style.opacity;
if ((val += .01) < 1){
el.style.opacity = val;
requestAnimationFrame(fade1);
}
}
fade1();
};
fadeIn();
fadeOut();
});
Thank you!
Still not the prettiest, but I have made just the minimum changes to your code to make it work: http://codepen.io/rlouie/pen/BzjZmK
First, you're assigning the opacity value back and forth repeatedly for no reason, which makes the code confusing to follow and also results in string concatenation instead of addition or subtraction, I have simplified this. Second, the functions were named the opposite of what they did, also confusing and fixed by me here. Finally, you ran both functions one after the other, so the second function set opacity to zero and then broke. Instead, I use a promise in your first function and resolve it when the animation completes.
That way the second function does not run until after the first one has completed animating.
var el = document.getElementById("img1");
el.addEventListener("click", function() {
function fadeOut() {
return new Promise(function (resolve, reject) {
let opacity = 1;
function fade(){
if ((opacity -= .01) > 0){
el.style.opacity = opacity;
requestAnimationFrame(fade);
} else {
resolve();
}
}
fade();
});
};
function fadeIn() {
let opacity = 0;
function fade1() {
if ((opacity += .01) < 1){
el.style.opacity = opacity;
requestAnimationFrame(fade1);
}
}
fade1();
};
fadeOut().then(fadeIn);
});
My proposal is:
start animation with fadein
when fadein finishes start the fadeout
var el = null;
function fadeIn(timestamp) {
var val = (+el.style.opacity == 0) ? 1 : +el.style.opacity;
if ((val -= .005) > 0) {
el.style.opacity = val;
window.requestAnimationFrame(fadeIn);
} else {
window.requestAnimationFrame(fadeOut);
}
}
function fadeOut(timestamp) {
var val = (+el.style.opacity == 0) ? 1 : +el.style.opacity;
if ((val += .005) < 1) {
el.style.opacity = val;
window.requestAnimationFrame(fadeOut);
}
};
window.onload = function () {
el = document.getElementById('img1');
el.addEventListener('click', function(e) {
window.requestAnimationFrame(fadeIn);
});
}
<img id="img1" src="http://www.loc.gov/pictures/static/data/highsm/banner.jpg">
Voor de fade in:
Function FadeIn() {
var milli = 3000; //duration
el = yourelement;
el.style.opacity = 1;
var a = 1 / (milli / 1000 * 16); //the -x
FadeIn_loop(a);
}
Function FadeIn_loop(a) {
if (el.style.opacity > 0.01) {
el.style.opacity = el.style.opacity - a;
setTimeout("FadeIn(" + el + ")", 16); //about 1/60 a second
} else {
el.style.opacity = 0;
}
}
Same thing for fade out, succes!
In your code are many things that does'nt seem to be right. First of get all those functions out of each other otherwise requestAnimationframe cant find the functions.

Making divs stack on top of each other during click through with pure JS

http://jsfiddle.net/Zgxv9/
As you can see in my fiddle, my divs go to their natural positions when clicking through them. I need whichever div was clicked last to always appear on top. My current code:
function displayOne() {
document.getElementById("fluid1").style.display = 'block';
}
function displayTwo() {
document.getElementById("fluid2").style.display = 'block';
}
function displayThree() {
document.getElementById("fluid3").style.display = 'block';
}
I would prefer to avoid jQuery for this if possible. Thank you!
I would try something like this.
Move them into a container on click, that way they keep their order, depending on the order in which they were moved into the container.
http://jsfiddle.net/Zgxv9/1/
var target = document.getElementById( "container");
function displayOne() {
target.appendChild(document.getElementById("fluid1"));
}
function displayTwo() {
target.appendChild(document.getElementById("fluid2"));;
}
function displayThree() {
target.appendChild(document.getElementById("fluid3"));
}
If you want them to be added to the top you can use insertBefore. It will work like this: http://jsfiddle.net/Zgxv9/7/
var target = document.getElementById( "container");
function displayOne() {
target.insertBefore(document.getElementById("fluid1"), target.firstChild);
}
function displayTwo() {
target.insertBefore(document.getElementById("fluid2"), target.firstChild);;
}
function displayThree() {
target.insertBefore(document.getElementById("fluid3"), target.firstChild);
}
DEMO — http://jsfiddle.net/Zgxv9/6/
var container = document.getElementById('container');
function displayOne() {
var div = document.getElementById("fluid1");
div.style.display = 'block';
container.insertBefore(div, container.firstChild);
}
You can use insertBefore method. Working demo.
function display(ev) {
ev.preventDefault();
var id = this.href.split('#')[1],
div = document.getElementById('fluid' + id),
divs = document.getElementsByClassName('container-fluid');
//if current div is not first insert it before the first one
div !== divs[0] && div.parentNode.insertBefore(div, divs[0]);
div.style.display = 'block'; //and show
}
[].forEach.call(document.getElementsByClassName('toggle'), function(link){
link.addEventListener('click', display);
});
The function could be more modular : http://jsfiddle.net/t76BX/58/
function displayDiv(elem_id) {
var elem = document.getElementById(elem_id);
elem.style.display = 'block';
var elemCloned = elem.cloneNode(true);
// console.log(elemCloned);
var theparentnode = elem.parentNode;
// console.log(theparentnode);
var divList = document.getElementsByClassName("container-fluid");
var first_element = divList[0];
theparentnode.insertBefore(elemCloned, first_element);
theparentnode.removeChild(elem);
}

Casino Roulette Game not working

http://csdev.cegep-heritage.qc.ca/students/cguigue/primordialCasino/game.html
supposed to click on the spin button and it should start the wheel spinning as well as changed the text on the screen in my displayArea, though when i click spin nothing happens,
getting undefined type error on the following code and not sure as to why
$('#wheel').rotate({
angle: 0,
animateTo: 2520,
duration: 4000
});
it says it isn't a function... :S
also...
if(currentGame.place == 0 && cellText == 0)
{
currentGame.setBet(betAmount * 40);
}
function rouletteGame(num, even, col)
{
this.place = num;
this.isEven = even;
this.colour = col;
this.win = 0;
this.hasBet = false;
this.setBet = function(bet)
{
this.win += bet;
this.hasBet = true;
}
says currentGame.place is undefined
but im initializing it in a for loop and its calling my above function...
for (var i = 1; i < rouletteWheel.length; ++i)
{
place = i;
if(i % 2 == 1)
{
isEven = false;
}
else
{
isEven = true;
}
if( i = red[count])
{
colour = "red";
++count;
}
else
{
colour = "black";
}
rouletteWheel[i] = new rouletteGame(place, isEven, colour);
}// for ()
.rotate() is not a built-in JQuery plugin. You will need to download or link the plugin in order for it to work. Add the following in your element of the HTML:
<script type="text/javascript" src="http://jqueryrotate.googlecode.com/svn/trunk/jQueryRotate.js"></script>
and see if that helps. with the first part of your problem.
As for the second part, I'm not sure if Javascript works this way too (I think it does), but you should create the new roulette game outside of the loop, and only change the values inside. Otherwise you are only creating a new roulette game for use within the scope of the for loop, not outside.
May want to check the documentation for this, as I'm not 100% positive about it. I just know it's how most other languages work.

how to attach click function to multiple divs without ID

I have a fade in function im trying to understand better. It works fine when I set up the
My question is if I have 8 links that already have the separate ID and class names how can I attach this function to each clickable link?
Is there a function to getElementbyClass or something and then just add the class to all my links?
here is my javascript:
var done = true,
fading_div = document.getElementById('fading_div'),
fade_in_button = document.getElementById('fade_in'),
fade_out_button = document.getElementById('fade_out');
function function_opacity(opacity_value) {
fading_div.style.opacity = opacity_value / 100;
fading_div.style.filter = 'alpha(opacity=' + opacity_value + ')';
}
function function_fade_out(opacity_value) {
function_opacity(opacity_value);
if (opacity_value == 1) {
fading_div.style.display = 'none';
done = true;
}
}
function function_fade_in(opacity_value) {
function_opacity(opacity_value);
if (opacity_value == 1) {
fading_div.style.display = 'block';
}
if (opacity_value == 100) {
done = true;
}
}
// fade in button
fade_in_button.onclick = function () {
if (done && fading_div.style.opacity !== '1') {
done = false;
for (var i = 1; i <= 100; i++) {
setTimeout((function (x) {
return function () {
function_fade_in(x)
};
})(i), i * 10);
}
}
};
// fade out button
fade_out_button.onclick = function () {
if (done && fading_div.style.opacity !== '0') {
done = false;
for (var i = 1; i <= 100; i++) {
setTimeout((function (x) {
return function () {
function_fade_out(x)
};
})(100 - i), i * 10);
}
}
};
Correcting the answer from BLiu1:
var fadeDivs = document.getElementsByClassName('fade');
for (var i=0, i<fadeDivs.length, i++){
// do stuff to all fade-divs by accessing them with "fadeDivs[i].something"
}
Have you considered using a javascript library like jQuery to manage this. They have some extensive, very easy to use "selectors" that allow you to easily get access to elements in the DOM and animate them with things like "fade ins" and "slides", etc. If you need more animations there are tons of plugins available for this. It also helps to deal with browser compatibility challenges too.
If you want to rely on pure JavaScript, you can use the document.getElementsByClassName() function defined here, but that function is only defined in IE9 and above as well as Safari, Chrome, FF, and Opera.
As said in the comments, there is a getElementsByClassName() method. Here is how you would use it.
for(var i=0; i<document.getElementsByClassName("fade").length; i++ ){
/*apply fade in function*/
}
I'm not sure whether getElementsByClassName() can detect one class name at a time. You might need regex for that.

Categories