I have programmed a bit in JS, but found my projects to become really long and unnecessarily complex. I want to learn OOP JS, and find it much easier to learn when my code get pictured in colors and figures. Here is a little example program:
var box1Left1 = 0;
var box1Left2;
var box2Left1 = 0;
var box2Left2;
setInterval(box1Fly, 10);
function box1Fly() {
// Fly Right
if ( box1Left1 < 300 ) {
box1Left1++;
document.getElementById("box1").style.left = box1Left1 + "px";
box1Left2 = box1Left1;
}
// Fly Left
if ( box1Left1 >= (300) ) {
box1Left2--;
document.getElementById("box1").style.left = box1Left2 + "px";
}
// Fly Right Again
if( box1Left2 == 0 ) { box1Left1 = box1Left2; }
}
setInterval(box2Fly, 10);
function box2Fly() {
// Fly Right
if ( box2Left1 < 300 ) {
box2Left1++;
document.getElementById("box2").style.left = box2Left1 + "px";
box2Left2 = box2Left1;
}
// Fly Left
if ( box2Left1 >= (300) ) {
box2Left2--;
document.getElementById("box2").style.left = box2Left2 + "px";
}
// Fly Right Again
if( box2Left2 == 0 ) { box2Left1 = box2Left2; }
}
<div id="box1" style="position:absolute; top: 10px; left: 0px; width: 50px; height: 50px; background-color: #aa39fc;"></div>
<div id="box2" style="position:absolute; top: 100px; left: 0px; width: 50px; height: 50px; background-color: #2c79f1;"></div>
As you can see, simple things get quite messy! Here is the deal: Can I make only one function, some sort of general function, that can handle both of these two flying boxes at the same time? Instead of, as now, having two functions ( box1Fly & box2Fly ) that are almost duplicates?
Thank you very much, Best Regards!
Would feel happier if the downvoter says why the answer is downvoted and more than happy to edit the answer to make it alright. :)
Why can't you just pass a parameter, which takes in which id should it use? By the way, there's no OO JS in this.
var box1Left1 = 0;
var box1Left2;
var box2Left1 = 0;
var box2Left2;
setInterval('boxFly("box1")', 10);
setInterval('boxFly("box2")', 10);
function boxFly(box_id) {
// Fly Right
if ( box1Left1 < 300 ) {
box1Left1++;
document.getElementById(box_id).style.left = box1Left1 + "px";
box1Left2 = box1Left1;
}
// Fly Left
if ( box1Left1 >= (300) ) {
box1Left2--;
document.getElementById(box_id).style.left = box1Left2 + "px";
}
// Fly Right Again
if( box1Left2 == 0 ) { box1Left1 = box1Left2; }
}
<div id="box1" style="position:absolute; top: 10px; left: 0px; width: 50px; height: 50px; background-color: #aa39fc;"></div>
<div id="box2" style="position:absolute; top: 100px; left: 0px; width: 50px; height: 50px; background-color: #2c79f1;"></div>
To convert into Object Oriented JavaScript, use this:
var box1Left1 = 0;
var box1Left2;
var box2Left1 = 0;
var box2Left2;
var box = function (id) {
this.id = id;
this.fly = function () {
// Fly Right
if ( box1Left1 < 300 ) {
box1Left1++;
document.getElementById(id).style.left = box1Left1 + "px";
box1Left2 = box1Left1;
}
// Fly Left
if ( box1Left1 >= (300) ) {
box1Left2--;
document.getElementById(id).style.left = box1Left2 + "px";
}
// Fly Right Again
if( box1Left2 === 0 ) { box1Left1 = box1Left2; }
};
this.startFlying = function () {
console.log(id);
setInterval(this.fly, 10);
};
};
box1 = new box("box1");
box2 = new box("box2");
box1.startFlying();
box2.startFlying();
<div id="box1" style="position:absolute; top: 10px; left: 0px; width: 50px; height: 50px; background-color: #aa39fc;"></div>
<div id="box2" style="position:absolute; top: 100px; left: 0px; width: 50px; height: 50px; background-color: #2c79f1;"></div>
Related
I am trying to make me character moving left and up and I think jump() and slideLeft()
functions are working properly and the problem is in the controller(e) function (else if (e.KeyCode===37)) . The first function is avaible but it isn't able to acces the second conditon function. Also, I would want to make the grid solid after I will make an slideRight() similar function ,so if my character is jumping on it, the platform would sustain the square . Has anyone any ideea for either of my questions ?
Code snippet:
var square = document.querySelector('.square');
var grid = document.querySelector('.grid');
var bottom = 0;
let isJumping = false;
let isGoingLeft = false;
var newBottom;
let left = 0;
let leftTimerId;
function jump() {
if (isJumping) return
let timerUpId = setInterval(function() {
if (bottom > 250) {
clearInterval(timerUpId);
let timerDownId = setInterval(function() {
if (bottom < 0) {
clearInterval(timerDownId);
isJumping = false;
}
bottom -= 5;
square.style.bottom = bottom + 'px';
}, 20)
}
isJumping = true;
bottom += 30;
square.style.bottom = bottom + 'px';
}, 20)
}
function slideLeft() {
console.log('da');
isGoingLeft = true;
leftTimerId = setInterval(function() {
left -= 5;
square.style.left = left + 'px';
}, 20)
}
function controller(e) {
if (e.keyCode === 32)
jump();
else if (e.KeyCode === 37)
slideLeft();
}
document.addEventListener('keydown', controller);
.grid {
position: absolute;
background-color: chartreuse;
height: 20px;
width: 500px;
bottom: 100px;
left: 100px;
}
.square {
position: absolute;
background-color: darkblue;
height: 100px;
width: 100px;
bottom: 0px;
left: 150px;
}
`
<div class="grid"></div>
<div class="square"></div>
EDIT:
There is a typo:
The second time you've written KeyCode
function controller(e) {
if(e.keyCode===32) {
jump();
}
else if(e.keyCode===37) {
slideLeft();
}
}
I don't really understand what you mean by the second part of your question. If you want a character to have the ability to jump on a square, you'll have to implement a collision detection. Something like this:
if ( isNotOnGround() ) {
fall()
}
For teaching myself javascript (and for getting/giving more insight in the field of astronomy :) ), I am setting up a page that displays relative positions of sun and moon.
Right now, the speed of the sun and moon movement is still fixed, but I would really like to make this dynamically user-definable via an input field. So, the initial speed is '30', and a user can speed this up or slow this down. Obviously, the ratio between sun and moon must stay fixed. I tried a lot of things (see some relics in the code, but I can't get it to work.
Anyone with more experience with javascript can assist me in doing this? Also, I notice CPU usage gets very high during this animation. Are there simple steps in making this script more efficient?
var dagen = 0;
function speed($this){
var speedSetting = $this.value;
//alert(speedSetting);
//return per;
}
function periode(bolletje, multiplier=30){
if (bolletje == 'zon'){var per = (multiplier*24/2);}
if (bolletje == 'maan'){var per = (multiplier*24*29.5/2);}
return per;
}
function step(delta) {
elem.style.height = 100*delta + '%'
}
function animate(opts) {
var start = new Date
var id = setInterval(function() {
var timePassed = new Date - start
var progress = timePassed / opts.duration
if (progress > 1) progress = 1
var delta = opts.delta(progress)
opts.step(delta)
if (progress == 1) {
clearInterval(id)
}
}, opts.delay || 10)
}
function terugweg(element, delta, duration) {
var to = -300;
var bolletje = element.getAttribute('id');
per = periode(bolletje);
document.getElementById(bolletje).style.background='transparent';
animate({
delay: 0,
duration: duration || per,
//1 sec by default
delta: delta,
step: function(delta) {
element.style.left = ((to*delta)+300) + "px"
}
});
if(bolletje == 'zon'){
dagen ++;
}
bolletje = element;
document.getElementById('dagen').innerHTML = dagen;
//setInterval(function (element) {
setTimeout(function (element) {
move(bolletje, function(p) {return p})
}, per);
}
function move(element, delta, duration) {
var to = 300;
var bolletje = element.getAttribute('id');
per = periode(bolletje);
document.getElementById(bolletje).style.background='yellow';
animate({
delay: 0,
duration: duration || per,
//1 sec by default
delta: delta,
step: function(delta) {
element.style.left = to*delta + "px"
}
});
bolletje = element;
//setInterval(function (element) {
setTimeout(function (element) {
terugweg(bolletje, function(p) {return p})
}, per);
}
hr{clear: both;}
form{display: block;}
form label{width: 300px; float: left; clear: both;}
form input{float: right;}
.aarde{width: 300px; height: 300px; border-radius: 150px; background: url('https://domain.com/img/aarde.png');}
#zon{width: 40px; height: 40px; background: yellow; border: 2px solid yellow; border-radius: 20px; position: relative; margin-left: -20px; top: 120px;}
#maan{width: 30px; height: 30px; background: yellow; border: 2px solid yellow; border-radius: 16px; position: relative; margin-left: -15px; top: 115px;}
<form>
<div onclick="move(this.children[0], function(p) {return p}), move(this.children[1], function(p) {return p})" class="aarde">
<div id="zon"></div>
<div id="maan"></div>
</div>
Dagen: <span id="dagen">0</span>
</form>
<form>
<label><input id="snelheid" type="range" min="10" max="300" value="30" oninput="speed(this)">Snelheid: <span id="snelheidDisplay">30</span></label>
</form>
First, change onlick to oninput in speed input tag.
<input id="snelheid" type="number" value="30" oninput="speed(this)">
And in your speed() function set multiplier = $this.value. multiplier should be global:
var multiplier = 30;
function speed($this){
console.log($this.value);
multiplier = $this.value;
//alert(speedSetting);
//return per;
}
function periode(bolletje){
if (bolletje == 'zon'){var per = (multiplier*24/2);}
if (bolletje == 'maan'){var per = (multiplier*24*29.5/2);}
return per;
}
Here is an example:
https://jsfiddle.net/do4n9L03/2/
Note: multiplier is not speed, it is delay. If you increase it it become slower
I'm trying to write a jQuery script that will continually scroll these <p> tags within their <div> parent. I got the idea from this site.
function shuffle(){
$('#wrapper > p').each(function(){
h = ($(this).offset().top + 130);
if( h > 500 ){
console.log(h);
$(this).css ('top', 0 );
return;
}
if( h == 270 ){
$(this).addClass('current' );
}
if( h == 360 ){
$(this).removeClass('current' );
}
$(this).animate({
top: h,
easing: 'easeIn'
}, 500, '');
if( h > 1350 ){
$(this).css ('top', 0 );
}
});
window.setTimeout(shuffle, 2500);
}
var i = 0;
$('#wrapper > p').each(function(){
starter = $(this).css('top', ((i * 90) ) + 'px' );
starterWhite = ($(this).offset().top + 130);
if((i*90) == 270)
$(this).addClass('current');
$(this).css('top', starter );
i++;
});
window.setTimeout(shuffle, 2000);
#wrapper {
height: 500px;
overflow: hidden;
position: relative;
}
p {
position: absolute;
margin: 0;
padding: 0;
}
.current {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
</div>
Problem is when I try to make it scroll the <p> tags overlap, and the highlighted tag doesn't change. Any idea how to make it work? Here's a JSFiddle of what I got so far.
Check this out:
// Constants, you can play with it
var STEP = 90;
var CURRENT_INDEX = 3;
// Variables for calculating
var currentTop = STEP * CURRENT_INDEX;
var nextForCurrentTop = STEP * (CURRENT_INDEX + 1);
var $numbers = $('#wrapper > p');
// In this case = 7
var count = $numbers.length;
var secondToLastTop = STEP * (count - 1);
$numbers.each(function(i) {
var $this = $(this);
$this.css('top', i * STEP + 'px');
if (i === CURRENT_INDEX) {
$this.addClass('current');
}
});
window.setTimeout(shuffle, 2000);
function shuffle() {
$numbers.each(function() {
$this = $(this);
// Calculating the new position of the element
h = parseInt($this.css('top')) + STEP;
// In this case = 540
if (h > secondToLastTop) {
$this.css('top', 0);
return;
}
// In this case visually = 3rd element
if (h === currentTop) {
$this.addClass('current');
}
// In this case visually = 4th element
if (h === nextForCurrentTop) {
$this.removeClass('current');
}
$this.animate({
top: h,
easing: 'easeIn'
}, 500, '');
});
window.setTimeout(shuffle, 2500);
}
#wrapper {
height: 500px;
overflow: hidden;
position: relative;
}
p {
position: absolute;
margin: 0;
padding: 0;
}
.current {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
<p>6</p>
<p>7</p>
</div>
I improved and commented code from your example, removed magic numbers. You can play with constants.
I have to have two images start on the left side of the screen and move to the right side and stop. Its like a race and whoever get to the right side first wins. I am generating a random number for this just, the images only move to the right once. I cant figure out why they are only moving once, and dont know how I would get them to stop on the right side.
Here's my code:
var myVar1 = setInterval(fly, 250);
function fly() {
var ranNum = Math.floor(Math.random()*2);
if(ranNum == 0){
document.getElementById("race").style.left = '25px';
} else if (ranNum == 1){
document.getElementById("race1").style.left = "25px";
}
}
body { background-image: url(images/stars.jpg); }
.img1 {
position: absolute;
bottom: 0px;
left: 0px;
}
.img2 {
position: absolute;
bottom: 200px;
left: 0px;
}
.img3 {
position: absolute;
top: 0px;
right: 0px;
}
<img src="images/tie.png" class="img1" id="race" alt="tie"></br>
<img src="images/xwing.png" class="img2" id="race1" alt="xwing">
<img src="images/death.png" class="img3" alt="dstar">
The third image(death.png aka death star), when its clicked it changes color and starts the "race" which I would use the onClick method for that, right? So once either the tie fighter or x-wing reaches the "finish line" on the right side, both images stop so we will have a winner. Also if the x-wing wins, I am going to have the dstar change to a dstar blowing up.
You need to increment the values in order to get it to move.
var leftIncrement = parseInt(document.getElementById("race").style.left) + ranNum + "px";
document.getElementById("race").style.left = leftIncrement;
At the moment you are setting it to "25px" every interval.
Try this:
var els = [document.getElementById("race"), document.getElementById("race1")],
timer = setInterval(fly, 250);
function fly() {
var el = els[Math.floor(Math.random()*2)],
newPos = (parseInt(el.style.left) || 0) + 1;
el.style.left = newPos + 'px';
if(newPos == 25) {
clearInterval(timer);
el.classList.add('winner');
}
}
var els = [document.getElementById("race"), document.getElementById("race1")],
timer = setInterval(fly, 250);
function fly() {
var el = els[Math.floor(Math.random()*2)],
newPos = (parseInt(el.style.left) || 0) + 1;
el.style.left = newPos + 'px';
if(newPos == 25) {
clearInterval(timer);
el.classList.add('winner');
}
}
body { background-image: url(images/stars.jpg); }
.img1 {
position: absolute;
bottom: 0px;
left: 0px;
}
.img2 {
position: absolute;
bottom: 200px;
left: 0px;
}
.img3 {
position: absolute;
top: 0px;
right: 0px;
}
.winner {
outline: 3px solid #0f0;
}
<img src="images/tie.png" class="img1" id="race" alt="tie"></br>
<img src="images/xwing.png" class="img2" id="race1" alt="xwing">
<img src="images/death.png" class="img3" alt="dstar">
It's because regardless of what random numbers you are generating, you are always assigned a left style value of 25px.
var left = document.getElementById("race").style.left;
left = left.replace('px','');
left += parseInt(left) + 25;
document.getElementById("race").style.left = left + "px";
Untested but should work.
This works
var racers = [ document.getElementById("race"), document.getElementById("race1") ];
var interval = setInterval( fly, 250 );
function fly() {
var racer = racers[ Math.floor(Math.random() * racers.length) ];
var newPos = parseInt( racer.style.left || 0 ) + 25;
racer.style.left = newPos + "px";
if( (newPos + racer.clientWidth) >= window.innerWidth){
clearInterval( interval );
alert( "And the winner is " + racer.id );
}
}
Here you got it in a JsFiddle http://jsfiddle.net/5poa7tnt/10/
Ask if you need help to understand
Edit : Looks similar to Oriol's post thought
Edit 2 : The race is most beautiful the a step of "1" instead of "25" and an interval of "5" or "10" instead of 250 .. I don't know what final result you want
I have the following code on my page:
$('#Report').click(Report);
function Report() {
var e = encodeURIComponent,
arr = [
"dataSource=" + e($('#DataSource').val()),
"statusID=" + e($('#StatusID').val())
];
window.location.href = '/Administration/Tests/Report?' + arr.join("&");
return false;
}
When a user clicks on the button with Id=Report then the function is called and it shows a page with report information.
However if the dataSource and statusID are not set then my code ends in an exception.
Is there some way I can check for the value of DataSource not being equal to "00" and StatusID not being equal to "0" and then show a dialog box telling the user these fields should be selected.
Ideally I would like to have something like the dialog box that Stackoverflow uses.
I'm not sure what 00 and 0 represent in your request, but I put them in there. I'm not familiar with that Stack Overflow dialog box, but here is some starting code to play with. The outer div (#error-frame) prevents clicking on any other elements while the box is displayed.
Demo: http://jsfiddle.net/ThinkingStiff/CW5wW/
Script:
function Report() {
var dataSource = $('#DataSource').val(),
statusId = $('#StatusID').val();
if( dataSource && statusId && dataSource != '00' && statusId != '0' ) {
var e = encodeURIComponent,
arr = [
"dataSource=" + e(dataSource),
"statusID=" + e(statusId)
];
window.location.href = '/Administration/Tests/Report?' + arr.join("&");
} else {
//error msg here, perhaps:
showError( 'Both Data Source and Status ID are required.' );
};
return false;
}
function showError( message ) {
document.getElementById( 'error-message' ).textContent = message;
document.getElementById( 'error-frame' ).style.display = 'block';
var error = document.getElementById( 'error' );
error.style.left = ( ( window.innerWidth / 2 ) - ( error.scrollWidth / 2 ) ) + 'px';
error.style.top = ( ( window.innerHeight / 2 ) - ( error.scrollHeight / 2 ) ) + 'px';
};
HTML:
<div id="error-frame"><div id="error"><div id="error-message"></div><button onclick="this.parentNode.parentNode.style.display='none'">OK</button></div></div>
CSS:
#error-frame {
display: none;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: 9999;
}
#error {
border: 4px solid darkgray;
height: 100px;
padding: 4px;
position: relative;
vwidth: 200px;
}
#error button {
position: absolute;
right: 0;
bottom: 0;
}