Empty array in form with button click and dynamic input positioning - javascript

I have a form that I am using to calculate the sum and average of an array of numbers. I am using a button to trigger the form to appear and then users can add extra input fields to enter as many values as they wish. When they click the 'Calc' button, they receive an alert of the sum and average. This much is working fine. The problem is when I click the trigger again to close and then to reopen the form, the same number of input fields as the user selected appear and, despite having been able to clear their values, I have not been able to empty the associated array. Thus, when the user inputs values the second time and attempts to perform the calculation, the previous values are being added to these new ones.
On top of this, I would like for the the dynamically added inputs to appear one on top of the other and for the '.remove-field' div (or at least the icon it contains) to appear to the right of each input field. I have tried various display values, positioning, etc. but nothing seems to produce a consistent look.
Here is my HTML markup:
<button class="form-launch" data-icon="&#xe17f">AVG</button>
<div class="form-space">
<form role="form" action="/wohoo" method="POST" class="form-add-remove">
<label class="label">Average Calculation</label>
<div id="horizontal_bar"></div>
<div class="multi-field-wrapper">
<div class="add-field"><i class="fa fa-plus-circle"></i></div>
<div class="multi-fields">
<div class="multi-field">
<input type="text" name="stuff[]" class="input-field"/>
<div class="remove-field"><i class="fa fa-minus-circle"></i></div>
</div>
</div>
</div>
<button type="button" class="check">Calc</button>
</form>
</div>
My CSS:
.form-launch {
position: absolute;
top: 20px;
left: 20px;
}
.form-space {
opacity: 0;
}
.form-add-remove {
font-family: "DJB Chalk It Up";
color: #FFF;
font-size: 30px;
width: 600px;
height: 300px;
padding: 20px;
border: 2px solid #FFF;
border-radius: 25px;
box-shadow: 0px 0px 10px 5px #000;
background: transparent url("http://mrlambertsmathpage.weebly.com/files/theme/blackboard.jpeg") repeat-y scroll left center;
text-align: center;
vertical-align: middle;
display: inline-flex;
-moz-box-pack: center;
justify-content: center;
align-items: center;
-moz-box-orient: vertical;
opacity: 1;
position: absolute;
top: 50%;
left: 50%;
margin-left: -300px;
margin-top: -125px;
display: inline-block;
}
.label {
position: absolute;
top: 20px;
left: 20px;
}
#horizontal_bar {
position: absolute;
top: 60px;
left: 0px;
width: 95%;
height: 4px;
border-radius: 2px;
background: #00A2E8 none repeat scroll 0% 0%;
margin: 2.5%;
box-shadow: 0px 0px 6px 3px #000, 0px 0px 1px #000 inset;
}
.multi-field-wrapper {
height: 130px;
width: 90%;
padding: 20px;
margin-left: 0px;
margin-top: 80px;
border: 2px dashed rgba(255, 255, 255, 0.1);
border-radius: 10px;
transition: all 1.5s ease-in-out 0.5S;
overflow-y: scroll;
}
.multi-field-wrapper:hover {
border: 2px solid rgba(255, 255, 255, 0.1);
transition: all 1.5s ease-in-out 0s;
}
.multi-field {
display: inline-block;
}
.add-field {
position: absolute;
right: 20px;
bottom: 20px;
}
i {
color: #00a2e8;
}
.calc {
position: absolute;
left: 20px;
bottom: 20px;
}
input {
font-family: "Borders Divide, But Hearts Shall Conquer";
border-radius: 5px;
border: 2px inset rgba(0, 0, 0, 0.4);
width: 100px;
text-align: right;
padding-right: 10px;
}
And my jQuery:
var launchCount = 0;
var arr = [],
sum = 0;
$('.form-launch').click(function() {
launchCount++;
if ((launchCount % 2) == 1) {
$('.form-space').css('opacity', '1');
// Initialize Average Form
$('.multi-field-wrapper').each(function() {
var $wrapper = $('.multi-fields', this);
$(".add-field", $(this)).click(function(e) {
$('.multi-field:first-child', $wrapper).clone(true).appendTo($wrapper).find('input').val('').focus();
});
$('.multi-field .remove-field', $wrapper).click(function() {
if ($('.multi-field', $wrapper).length > 1)
$(this).parent('.multi-field').remove();
});
});
$(".calc").click(function() {
$("input[type=text]").each(function() {
arr.push($(this).val());
sum += parseInt($(this).val());
});
var n = arr.length;
var AVG = (sum / n);
alert(sum + "," + AVG);
});
// End Average Form
} else if ((launchCount % 2) == 0) {
$('.form-space').css('opacity', '0');
$('.form-add-remove').find("input[type=text]").val('');
if ($('.multi-field', $wrapper).length > 1) {
$(this).parent('.multi-field').remove(); // does not seem to work!
}
arr = []; // also does not seem to work
}
});
I have commented a few lines at the bottom of my jQuery to illustrate what I have tried. I also looked at setting the array length to 0, but I was not able to get that to work either.
Obviously, this is a work in progress. My jsfiddle is here: http://jsfiddle.net/e3b9bopz/77/

Can you try this?
$(".calc").click(function() {
$("input[type=text]").each(function() {
arr.push($(this).val());
sum += parseInt($(this).val());
});
var n = arr.length;
var AVG = (sum / n);
alert(sum + "," + AVG);
arr = []; # How about putting your reset here?
sum = 0; # reinitialized the sum
});
I think you need to reset the arr after you make a calculation.

Not exactly what you need, but move $(".check").click out of $('.form-launch').click, and wrap the whole thing in a jquery ready.
$(function() {
$(".check").click(function() {
$("input[type=text]").each(function() {
arr.push($(this).val());
sum += parseInt($(this).val());
});
var n = arr.length;
var AVG = (sum / n);
alert(sum + "," + AVG);
arr = [];
});
})
JSFiddle

Related

Weird scrollTop function behavior - JQuery

I'm trying to change the css position from fixed to static and viceversa, based on pixel scrolled...
The script works fine as espected, but at the point to change css position, there is a sort of lag.
If i scroll slow till at the point of switch, from the console i see the position switch fast from fixed to static and from static to fixed.
Anyway, look in the snippet, scroll near the end, and see what happen... I'm not able to figure out the reason. Hope in your help! Thanks!
Open the snipped in fullscreen to see better!
$(window).scroll(function() {
var scrolled = $(window).scrollTop();
var add_px = $('body').height();
var px_scroll = scrolled + add_px;
var tot = $(document).height();
var ftr = $('#footer').css("margin-bottom");
ftr = ftr.replace('px','');
ftr = ftr.replace('-','');
var total = tot - ftr;
if ( px_scroll > total ) {
$('#act_btns').css({'position':'static'});
} else {
$('#act_btns').css({'position':'fixed'});
}
});
html, body { height: 100%; margin:0; padding: 0; }
#main_container {
position: relative;
width: 100%;
height: auto;
min-height: 100%;
text-align: center;
}
#act_btns {
position: fixed;
margin: 0 auto;
left: 0;
right: 0;
bottom: 50px;
}
#act_btns input {
color: #fff;
border: 0px;
width: 100px;
height: 40px;
margin: 0 5px;
box-shadow: 0 0 5px 5px #000;
}
#footer {
position: absolute;
bottom: 0;
margin-bottom: -200px;
width: 100%;
background: rgba(0, 0, 0, 0.8);
padding: 10px 7px 15px 7px;
box-sizing: border-box;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<html>
<body>
<div id="main_container">
<div style="position:relative;margin:0 auto 20px;width:80%;height:2500px;background:#ccc;"></div>
<div id="act_btns">
<input type="submit" name="save_list" id="save_btn" value="Salva">
<input type="submit" name="reset_list" id="rst_btn" value="Reset">
</div>
<div id="footer"><p id="copyright">Copyright © 2016 - 2021</p></div>
</div>
</body>
</html>
The problem you are facing is: You calculate the total value on every change of the scroll position. So when you scroll and change the position of the element from fixed to static you will add the height (60px) to total. (This is visible if you console.log(scrolled, total)). Because fixed position elements do not take up any space.
The most simple fix is to calculate the total when the page is loaded. And then, if it doesn't change you're good to go with that height forever. So the only change I did from your code is to move the calculation of total outside of the scroll function.
var tot = $(document).height();
var ftr = $('#footer').css("margin-bottom");
ftr = ftr.replace('px','');
ftr = ftr.replace('-','');
var total = tot - ftr;
$(window).scroll(function() {
var scrolled = $(window).scrollTop();
var add_px = $('body').height();
var px_scroll = scrolled + add_px;
if ( px_scroll > total ) {
$('#act_btns').css({'position':'static'});
} else {
$('#act_btns').css({'position':'fixed'});
}
});
html, body { height: 100%; margin:0; padding: 0; }
#main_container {
position: relative;
width: 100%;
height: auto;
min-height: 100%;
text-align: center;
}
#act_btns {
position: fixed;
margin: 0 auto;
left: 0;
right: 0;
bottom: 50px;
}
#act_btns input {
color: #fff;
border: 0px;
width: 100px;
height: 40px;
margin: 0 5px;
box-shadow: 0 0 5px 5px #000;
}
#footer {
position: absolute;
bottom: 0;
margin-bottom: -200px;
width: 100%;
background: rgba(0, 0, 0, 0.8);
padding: 10px 7px 15px 7px;
box-sizing: border-box;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<html>
<body>
<div id="main_container">
<div style="position:relative;margin:0 auto 20px;width:80%;height:2500px;background:#ccc;"></div>
<div id="act_btns">
<input type="submit" name="save_list" id="save_btn" value="Salva">
<input type="submit" name="reset_list" id="rst_btn" value="Reset">
</div>
<div id="footer"><p id="copyright">Copyright © 2016 - 2021 VirtualCode.Net</p></div>
</div>
</body>
</html>
This could lead to some problems if you are loading images and what not which may take up more space (height) when completely loaded and the calculation already happened. To never face that issue you can wrap the calculation inside
$(window).load(function(){
// add total calculation code here
});

Make dots active on Slider

I have this Slider example created with pure JS.
The slider is working great. The only thing left to do would be to activate the three dots so when the 1st slide opens, 1st dot activates, showing different color than the other dots, and so on. Also, you should be able to open the correct slide when clicking dots, so 1st dot opens 1st slide, 2nd dot 2nd slide, and so on.
Could you help me to achieve this? You can find the source code below.
const nextBtn = document.querySelector('.nextBtn');
const prevBtn = document.querySelector('.prevBtn');
const container = document.querySelector('.images');
const offers = document.getElementById('offers');
const link = document.getElementById('links');
let colors = ['#7f86ff', '#2932d1', '#00067f'];
let currentSlide = 0;
let texts = ['Change1', 'Change2', 'Change3'];
let currentText = 0;
let links = ['Link1', 'Link2', 'Link3'];
let currentLink = 0;
function updateSlide(direction) {
currentSlide =
(colors.length + currentSlide + direction)
% colors.length;
container.style.backgroundColor = colors[currentSlide];
container.animate([{opacity:'0.1'}, {opacity:'1.0'}],
{duration: 200, fill:'forwards'})
}
function updateText(direction) {
currentText =
(texts.length + currentText + direction)
% texts.length;
offers.innerHTML = texts[currentText];
offers.animate([{transform:'translateY(-50px)', opacity:'0.0'}, {transform:'translateY(0)', opacity:'1.0'}],
{duration: 200, fill:'forwards'})
}
function updateLink(direction) {
currentLink =
(links.length + currentLink + direction)
% links.length;
link.innerHTML = links[currentLink];
link.animate([{transform:'scale(0,0)'}, {transform:'scale(1.1)'}],
{duration: 200, fill:'forwards'})
}
updateSlide(0);
updateText(0);
updateLink(0);
nextBtn.addEventListener('click', nextSlide);
prevBtn.addEventListener('click', prevSlide);
function nextSlide() {
updateSlide(+1);
updateText(+1);
updateLink(+1);
clearInterval(myInterval);
}
function prevSlide() {
updateSlide(-1);
updateText(-1);
updateLink(-1);
clearInterval();
clearInterval(myInterval);
}
var myInterval = window.setInterval(function(){
updateSlide(+1),updateText(+1),updateLink(+1); },
8000);
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: lightblue;
}
.images {
background-color: #4047c9;
flex: 0 0 80%;
min-height: 70vh;
border-radius: 10px;
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
color: white;
}
#links {
text-decoration: none;
color: white;
border: solid 2px white;
border-radius: 3px;
padding: 5px 10px;
}
#links:hover {
background-color: #000238;
}
a {
color: white;
text-decoration: none;
}
.dots {
display: flex;
margin-top: 120px;
margin-bottom: 50px;
}
#dot1, #dot2, #dot3 {
width: 20px;
height: 20px;
background-color: rgb(147, 151, 249);
border-radius: 50%;
margin: 0px 5px;
cursor: pointer;
}
#dot1:active, #dot2:active, #dot3:active {
background-color: #fff;
}
.btn {
display: inline-block;
background: white;
color: black;
padding: 10px;
border: none;
cursor: pointer;
}
.prevBtn {
position: absolute;
top: 50%;
left: 0;
transform: translate(-50%, -50%);
}
.nextBtn {
position: absolute;
top: 50%;
right: 0;
transform: translate(50%, -50%);
}
.btn:active {
background-color: grey;
color: white;
}
.btn:hover {
background-color: grey;
color: white;
}
<body>
<div class="images">
<button type="button" class="btn prevBtn">Prev Btn</button>
<button type="button" class="btn nextBtn">Next Btn</button>
<h1 id="offers">Changing text</h1>
Links
<div class="dots">
<span id="dot1"></span>
<span id="dot2"></span>
<span id="dot3"></span>
</div>
</div>
</body>
First off, according to
https://developer.mozilla.org/en-US/docs/Web/CSS/:active
The :active CSS pseudo-class represents an element (such as a button) that is being activated by the user.
So if you want your dots to be active, you’ll have to write a different way of giving them an active state since they are currently <span> tags, I would recommend giving them a class of .active, and adding in Javascript code to add that class on to them, or adding in that style programmatically within the Javascript function.
Based on your other request though, you will most likely also have to make the dots an <a> tag or something along those lines so you can add functionality on to them to let clicking on the dots bring you to any slide. Something probably along the lines of:
function dot1Click() {
updateSlide(1);
updateText(1);
updateLink(1);
dot1.style.backgroundColor = #fff;
}
Then you should have something along the lines of what you want. I'll return to this question when I have more time to iron out a code snippet, but I wanted to give you something to help you get started!

Changing div left property set in % using javascript/jQuery?

Hope you can help me!! So I have a div inside another div and I'd like to move the second one back and forth with a step of 14.5% left and right stopping it before the black edges. I've managed to do it setting the left property in px but I'd like to to that with percentages..how can I do that? Thanks in advance!
PS. of course now the code doesn't work well because of the px changing..for this reason I'd like to work with %s...
$(document).ready(function() {
$('#min_oct').click(function() {
var left = parseFloat($('.highlighted').css('left'));
console.log(left);
if(left<99.495){
$('.highlighted').css('left',left);
}
else{
left= left - 103.108;
$('.highlighted').css('left',left);
}
});
});
$(document).ready(function() {
$('#plus_oct').click(function() {
var left = parseFloat($('.highlighted').css('left'));
console.log(left);
if(left>411.111){
$('#highlighted').css('left',left);
}
else{
left= left + 103.108;
$('#highlighted').css('left',left);
}
});
});
.mini_keyboard{
position: relative;
width: 700px;;
height: 90px;
top: 22.5%;
transform: translate(35%);
border: 0.5rem solid;
box-shadow:
inset 0 0 18rem black,
inset 0 0 4rem black,
0 0 10rem black;
padding: 0.5%;
bottom: 5px;
}
.highlighted{
position: absolute;
background-color: yellow;
width: 198px;;
height: 93px;
left: 57.5%;
top: 0.5%;
opacity: 0.6;
padding: 0.5%;
bottom: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mini_keyboard">
<div id=highlight class="highlighted"></div>
</div>
<button id="min_oct">-1 octave</button>
<button id="plus_oct">+1 octave</button>
First, your highlighted id is missing " and you're are trying to get your element by calling the id attribute with the class value.
You can get the container width with .width() function, and then calculate the percentage by multiplying it by 0.145.
$(document).ready(function() {
$('#min_oct').click(function() {
var containerWidth = $(".mini_keyboard").width();
var left = parseFloat($('.highlighted').css('left'));
console.log(left);
var step = (containerWidth * 0.145);
if(left < step){
$('#highlight').css('left',left);
}
else{
left= left - step;
$('#highlight').css('left',left);
}
});
});
$(document).ready(function() {
$('#plus_oct').click(function() {
var containerWidth = $(".mini_keyboard").width();
var left = parseFloat($('.highlighted').css('left'));
console.log(left);
var step = (containerWidth * 0.145);
if(left > (containerWidth - (2*step))){
$('#highlight').css('left',left);
}
else{
left = left + step;
$('#highlight').css('left',left);
}
});
});
.mini_keyboard{
position: relative;
width: 700px;;
height: 90px;
top: 22.5%;
transform: translate(35%);
border: 0.5rem solid;
box-shadow:
inset 0 0 18rem black,
inset 0 0 4rem black,
0 0 10rem black;
padding: 0.5%;
bottom: 5px;
}
.highlighted{
position: absolute;
background-color: yellow;
width: 198px;;
height: 93px;
left: 57.5%;
top: 0.5%;
opacity: 0.6;
padding: 0.5%;
bottom: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mini_keyboard">
<div id="highlight" class="highlighted"></div>
</div>
<button id="min_oct">-1 octave</button>
<button id="plus_oct">+1 octave</button>

try to setTimeout to show and hide the balls

I tried to write a program to practice my js skills. There are 3 balls and they are hidden at first. I want the ball_1 shows up first, and after 1 sec, ball_1 disappears. Next, ball_2 shows up and after 1 sec it disappears; same logic goes with ball_3. When I run my code, the first two balls does not hide. I am not sure what is going wrong. The code below are the html, css, and js code that i wrote. Hope someone could help me out. Thank you in advance.
$(document).ready(function() {
var notes = ['ball_1', 'ball_2', 'ball_3'];
for (i = notes.length; i > 0; i--) {
var note = notes.shift();
$('#' + note).addClass('shown');
setTimeout(function() {
$('#' + note).removeClass('shown');
}, 1000);
}
});
#ball_1 {
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2 {
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3 {
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1,
#ball_2,
#ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="ball">
<div id="ball_1" class="not_shown"></div>
<div id="ball_2" class="not_shown"></div>
<div id="ball_3" class="not_shown"></div>
</div>
In general never modify an array when iterating using a for loop. The shift method will remove the first item from the array thus modifying it's length. Instead do this:
$(document).ready(function() {
var notes = ['ball_1','ball_2','ball_3'];
var i; // You were declaring "i" in global namespace before. Don't do that.
for(i = 0; i < notes.length; i++){
var note = notes[i];
$('#' + note).addClass('shown');
setTimeout(function() {
$('#' + note).removeClass('shown');
},1000);
}
});
Also you will see from my note that you were defining "i" in the global namespace. It is never good to do that so always make sure to define your variables at the beginning of the function block if using "var".
EDIT: missed a semicolon
EDIT2: completely missed that i needed to change up the loop condition.
You are looking for an asnychronous play of events - first ball_1 shows up for 1 sec and after that ball_2 shows up for 1 sec and so forth.
Something like this won't work:
for( var i = 0; i < notes.length; i++){
$('#' + notes[i]).addClass('shown');
setTimeout(function() {
$('#' + notes[i]).removeClass('shown');
},1000);
}
because the timeouts will be registered one after the other in quick succession and all the balls will show up and hide in little over one second.
So you can create a callback and set the timeout for the next ball only after the previous ball has been shown fully for 1 sec - see demo below:
$(document).ready(function() {
var notes = ['ball_1', 'ball_2', 'ball_3'];
hideBall(notes,0);
});
function hideBall(notes,i) {
$('#' + notes[i]).addClass('shown');
hide(function() {
if(++i < notes.length) {
hideBall(notes,i);
}
}, notes[i]);
}
function hide(callback, note) {
setTimeout(function() {
$('#' + note).removeClass('shown');
callback();
}, 1000);
}
#ball_1 {
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2 {
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3 {
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1,
#ball_2,
#ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div id="ball">
<div id="ball_1" class="not_shown"></div>
<div id="ball_2" class="not_shown"></div>
<div id="ball_3" class="not_shown"></div>
</div>
Hope this is what you need
$(document).ready(function() {
var notes = ['ball_1','ball_2','ball_3'];
for(i = notes.length; i > 0; i--){
var note = notes[i];
$('#' + note).addClass('shown');
hideBall(note, i)
}
});
function hideBall(note) {
setTimeout(function() {
$('#' + note).removeClass('shown');
},1000 * i);
}
#ball_1{
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2{
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3{
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1, #ball_2, #ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = "ball">
<div id = "ball_1" class = "not_shown"></div>
<div id = "ball_2" class = "not_shown"></div>
<div id = "ball_3" class = "not_shown"></div>
</div>
What you are trying won't work as it will run the for loop all in one go, setting up 3x timeouts.
try something like this
jQuery(document).ready(function($) {
function myBallLoop(){
// increment as needed
if(typeof note == 'undefined') {
var note = 1;
} else if (note == 3){
break; // end loop
} else {
note ++;
}
// show current ball qickly
$('#ball_' + note).show('fast', function(){
// call back after show event
// hide current ball after 1 sec
r = setTimeout(function(){$('#ball_' + note).hide()}, 1000);
// self call function after 2 seconts
t = setTimeout(function(){myBallLoop();, 2000}
});
}
// loop start
myBallLoop();
});
Take advantage of what jquery gives you.
Iterate using $.each is also the same as ES5's forEach. Using delay method to delay a function of adding classes is similar to setTimeout.
$(document).ready(() => {
var notes = ['ball_1','ball_2','ball_3'];
let showBalls = (i, item) => {
$('#' + item).delay(i * 1000).queue(() => {
$('#' + item).addClass('shown');
$('#' + notes[i - 1]).removeClass('shown').clearQueue();
});
}
$.each(notes, (i, item) => {
showBalls(i, item);
});
});
#ball_1{
width: 10px;
height: 10px;
background: #000000;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_2{
width: 10px;
height: 10px;
background: #0000FF;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_3{
width: 10px;
height: 10px;
background: #7FFF00;
border: 2px solid #ccc;
border-radius: 50%;
}
#ball_1, #ball_2, #ball_3 {
width: 10px;
height: 10px;
border: 2px solid #ccc;
border-radius: 50%;
}
.not_shown {
display: none;
}
.shown {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = "ball">
<div id = "ball_1" class = "not_shown"></div>
<div id = "ball_2" class = "not_shown"></div>
<div id = "ball_3" class = "not_shown"></div>
</div>

Limit a DIV to appear within another DIV of specific size

I'm currently working on this small project that randomly displays a div (#box) of 100px width and height. I want this div to appear ONLY in another div (#boxBorder) so it appears to be limited to a specific area on the page.
Here is the content of my HTML:
<h1>Test your reactions!</h1>
<p id="directions">Click the shape as fast as you can!</p>
<p id="scoreC">Click score: <span id="cScore">0</span>s</p>
<p id="scoreT">Total score: <span id="tScore">0</span>s</p>
<div id="boxBorder"></div>
<div id="box"></div>
Here is the CSS:
#boxBorder {
height: 500px;
width: 500px;
margin: 20px auto;
left: 0;
right: 0;
background-color: white;
border: 1px black solid;
position: absolute;
z-index: 0;
}
#box {
margin: 0 auto;
height: 100px;
width: 100px;
background-color: red;
display: none;
border-radius: 50px;
position: relative;
z-index: 1;
}
h1 {
margin: 15px 0 0 0;
}
#directions {
margin: 0;
padding: 5px;
font-size: 0.8em;
}
#scoreT, #scoreC {
font-weight: bold;
margin: 10px 50px 0 0;
}
#tScore, #cScore {
font-weight: normal;
}
h1, #directions, #scoreT, #scoreC {
width: 100%;
text-align: center;
}
And lastly, the javascript function for random position:
//Get random position
function getRandomPos() {
var pos = Math.floor((Math.random() * 500) + 1);
console.log("POS: " + pos + "px");
return pos + "px";
}
Which I call within a timeout method:
setTimeout(function() {
createdTime = Date.now();
console.log("make box: " + createdTime);
document.getElementById("box").style.top=getRandomPos();
document.getElementById("box").style.left=getRandomPos();
document.getElementById("box").style.backgroundColor=getRandomColor();
document.getElementById("box").style.borderRadius=getRandomShape();
document.getElementById("box").style.display="block";
}, rTime);
I'm not very skilled in positioning and I can't seem to get these two divs to align so that the #box div can recognize the size of the #boxBorder div and stay within those limits. Any help would be appreciated!
Couple things wrong here:
You need the box div nested inside the borderBox div if you want to use the relative positioning.
<div id="boxBorder">
<div id="box"></div>
</div>
The randomPos function needs to take into account the size of the box, so only multiply by 400 instead of 500.
function getRandomPos() {
var pos = Math.floor((Math.random() * 400));
return pos + "px";
}
Set the style to inline-block, not block for the box.
Use setInterval instead of setTimeout to have it repeat.
var rTime = 1000;
function getRandomPos() {
var pos = Math.floor((Math.random() * 400));
console.log("POS: " + pos + "px");
return pos + "px";
}
function getRandomColor() {
return ['#bf616a', '#d08770', '#ebcb8b', '#a3be8c', '#96b5b4', '#8fa1b3', '#b48ead'][(Math.floor(Math.random() * 7))];
}
function randomizeBox() {
createdTime = Date.now();
console.log("make box: " + createdTime);
document.getElementById("box").style.top = getRandomPos();
document.getElementById("box").style.left = getRandomPos();
document.getElementById("box").style.backgroundColor = getRandomColor();
}
setInterval(randomizeBox, rTime);
#boxBorder {
height: 500px;
width: 500px;
margin: 20px auto;
left: 0;
right: 0;
background-color: white;
border: 1px black solid;
position: absolute;
z-index: 0;
}
#box {
margin: 0 auto;
height: 100px;
width: 100px;
border-radius: 50px;
position: relative;
z-index: 1;
display: inline-block;
}
h1 {
margin: 15px 0 0 0;
}
#directions {
margin: 0;
padding: 5px;
font-size: 0.8em;
}
#scoreT,
#scoreC {
font-weight: bold;
margin: 10px 50px 0 0;
}
#tScore,
#cScore {
font-weight: normal;
}
h1,
#directions,
#scoreT,
#scoreC {
width: 100%;
text-align: center;
}
<h1>Test your reactions!</h1>
<p id="directions">Click the shape as fast as you can!</p>
<p id="scoreC">Click score: <span id="cScore">0</span>s</p>
<p id="scoreT">Total score: <span id="tScore">0</span>s</p>
<div id="boxBorder">
<div id="box"></div>
</div>

Categories