I'm trying to change a position of a image that I have in HTML by using javascript. I can actually get it working if I have the following code:
function main()
{
var catOne = document.getElementById("cat1");
catOne.style.left = cat1.getX().toString() + "px";
catOne.style.top = cat1.getY().toString() + "px";
}
but when I change the code to this:
var catOne = new Cat("cat1", 300, 100);
function main()
{
catOne.setUp();
}
it doesn't work. and I dont know why, but it only gives me an error of "TypeError: Cannot read property 'style' of null"
This is my Cat class in javascript:
function Cat(id, x, y)
{
this.cat = document.getElementById(id);
this.x = x;
this.y = y;
}
Cat.prototype.setUp = function ()
{
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Cat.prototype.getX = function ()
{
return this.x;
};
Cat.prototype.getY = function ()
{
return this.y;
};
TypeError: Cannot read property 'style' of null means your catOne does not exist in the DOM tree.
You should instantiate the Cat class when the DOM is ready (or on window load).
I don't know why you need that main() function but when does it execute? It should also execute when the DOM is ready.
var catOne;
function main() {
catOne.setUp();
}
window.onload = function() {
catOne = new Cat("cat1", 300, 100);
main();
}
I also suggest that you set the position of your cat to absolute if you are positioning it like that in your setUp() function. (I think you are already doing this with your CSS):
Cat.prototype.setUp = function ()
{
this.cat.style.position = 'absolute';
this.cat.style.left = this.x.toString() + "px";
this.cat.style.top = this.y.toString() + "px";
};
Here is the fiddle.
Other than that your code should work.
with:
var catOne = new Cat("cat1", 300, 100);
catOne.setUp();
works just fine.
I don't quite get it how You managed to get error You mentioned
link: http://jsfiddle.net/Z74mM/
Related
Hello i am trying to make a class to have numerous object changing background images on a site without creating each object one by one.
So i have done this to change the background image of one "object" :
let x = 0; //index
const image = ["assets/img1.jpeg", "assets/img2.jpeg", "assets/img3.jpeg"]; //images to show
function displayNextImage() {
x = (x === 2) ? 0 : x + 1;
document.getElementById("myID").setAttribute("style", "background-image: url(" + image[x] + ")") //change images
};
function startTimer() {
setInterval(displayNextImage, 3000); //start looping
}
startTimer();
It work and so i want to make it a class :
class changingImageObject {
constructor(img1, img2, img3, id) {
this.image = [img1, img2, img3];
this.id = id;
this.x = 0;
};
displayNextImage() { //Change the showed image x+1
this.x = (this.x === 2) ? 0 : this.x + 1;
document.getElementById(this.id).setAttribute("style", "background-image: url(" + this.image[this.x] + ")");
};
startTimer() { //Change image after 3sec (looping)
setInterval(this.displayNextImage, 3000);
};
}
const changingImages = new changingImageObject("assets/img1.jpeg", "assets/img2.jpeg", "assets/img3.jpeg", "myID");
changingImages.startTimer();
I added the script at the end of the html, it create the object but the displayNextImage function give a error : Uncaught TypeError: Cannot read property 'setAttribute' of null
at displayNextImage
Thx for reading
It seems i needed to bind my method to the constructor, thanks to Mubaraq.
Code with correction.
constructor(img1, img2, img3, id) {
this.image = [img1, img2, img3];
this.id = id;
this.x = 0;
this.displayNextImage = this.displayNextImage.bind(this);
};
Now i need to learn the use of bind :)
I have homework from university, classic 15 puzzle. I have problem with those two styles. Here is the code that i have problem
function siirra_pala(pala) {
var palaRivi = parseInt(pala.style.top) / palanKoko;
var palaSarake = parseInt(pala.style.left) / palanKoko;
}
Error code is "Uncaught TypeError: Cannot read property 'top' of undefined" and "Uncaught TypeError: Cannot read property 'left' of undefined".
If it helps:
siirra_pala(pala) is move_tile(tile)
palaRivi is tileRow and palaSarake is tileColumn
palanKoko is tileSize.
I have palanKoko set to 100. And style is defined in:
function muodosta_palat(pelialue) {
for (var y = 0; y < 4; y++) {
for (var x = 0; x < 4; x++) {
if (!(x === tyhja_paikka.x && y === tyhja_paikka.y)) {
var pala = document.createElement('div');
pala.id = 'pala' + x + y;
pala.textContent = 4 * y + x + 1;
pala.style.left = x * palanKoko + 'px';
pala.style.top = y * palanKoko + 'px';
pala.className = 'pala';
pelialue.appendChild(pala);
}
}
}
If you need more code, please tell which one. Thank You
#Bergi:
window.onload = function () {
muodosta_palat(document.getElementById('pelialue'));
var palat = document.querySelectorAll(".pala");
document.getElementById('sekoitusnappi').onclick = sekoita;
for (var i = 0; i < palat.length; i++) {
palat[i].addEventListener("click", siirra_pala);
palat[i].addEventListener("mouseover", mouseOver);
palat[i].addEventListener("mouseout", mouseOut);
}
};
From your error it would seem pala is undefined (not set, doesn't exist), at least not in the scope of that function.
Variable pala is created within a function, and it's only known in this function. What you want to do is capture the click event, and pass what was clicked to the function.
If you change call to the function..
palat[i].addEventListener("click", function () { siirra_pala(this) });
the reference should be ok.
Here:
palat[i].addEventListener("click", siirra_pala);
the parameter passed to siirra_pala is the click event, not the clicked element. You should modify your function to either select the clicked element property from the event object or simply use this.
See this:
document.getElementById('x').addEventListener("click", handler);
function handler(e) {
console.log(e); // full event object
console.log(this); // clicked element
this.style.background = "#aaa";
}
#x {
width: 50px;
height: 50px;
background: #eee;
}
<div id="x"></div>
So the fix for your function would be something like this:
function siirra_pala(pala) {
var palaRivi = parseInt(this.style.top) / palanKoko;
var palaSarake = parseInt(this.style.left) / palanKoko;
}
(bear in mind that this function is not very useful)
Hello stackoverflow community!
First I must say that I dont have much experience with constructors.
So. What I am trying to do, is to animate a parachutist to fly from top to bottom of the screen.
I thought I could use a constructor to set up a parachutist:
var parachute = function() {
this.height = 35;
this.width = 30;
this.speed = 50;
this.xPos = Math.round(Math.random() * (window.width - this.width));
this.animate = function() {
this.img = new Image();
this.yPos = 0;
this.img.onload = function() {
ctxPara.globalCompositeOperation = 'copy';
ctxPara.translate(0, this.yPos);
ctxPara.drawImage(this.img, this.xPos, 0);
};
this.img.src = 'para.png';
this.yPos++;
};
};
This constructor is used in a function called 'fly':
var fly = function() {
var newParachute = new parachute();
setInterval(newParachute.animate, newParachute.speed);
};
And this 'fly' function is triggered when the window loads:
window.onload = function() {
var canvasBg = document.getElementById('canvasBg');
// I splitt the Background and the parachutists in two canvas elements
// handling the problem (to erase content and draw new content) with
// the canvas animation.
var canvasPara = document.getElementById('canvasPara');
ctxPara = canvasPara.getContext('2d');
canvasPara.width = window.width;
canvasPara.height = window.height;
canvasBg.width = window.width;
canvasBg.height = window.height;
fly();
clouds(); // background is loading here
};
What you should see, is a Parachutist flying down the screen. But unfortunately you don't...
Now, after that Long text. (Iam very sorry that it is so long :-( ) My question is: Do you know what I am doing wrong? Is my constuctor correct? Is, what i am trying to do, supposed to be written like this? Any advices or suggestions for a succesfull opportunity? (I hope my english isn't that terrible I think it is :-) )
Oh i forgot to mention the error. It's a TypeMissMatchError.
That means 'this.img' is not an img element at this line:
ctxPara.drawImage(this.img, this.xPos, 0);
Now, I followed the example of markE.
Instead of showing me a parachutist. It shows me an error in this line: ctxPara.drawImage(this.img, this.xPos, this.yPos);
var fly = function () {
var newParachute = new parachute();
newParachute.img.load.call(newParachute);
setInterval(newParachute.animate.call(newParachute), newParachute.speed);
};
var parachute = function () {
this.height = 35;
this.width = 30;
this.speed = 25;
this.xPos = Math.round(Math.random() * (window.innerWidth - this.width));
this.img = new Image();
this.yPos = 0;
this.img.isLoaded = false;
this.img.load = function () {
this.img.isLoaded = true;
};
this.img.src = 'parachute.png';
this.animate = function () {
if (this.img.isLoaded) {
ctxPara.clearRect(0, 0, canvasPara.width, canvasPara.height);
ctxPara.drawImage(this.img, this.xPos, this.yPos); // ERROR: 'Unknown Error'.
this.yPos++;
console.log('animating');
}
};
};
I am stuck again. But now i don't even know the reason... Please help!?
Demo: http://jsfiddle.net/m1erickson/ym55y/
A couple of issues:
(1) To get the window width you can use:
window.innerWidth
(2) setInterval calls newParachute.animate.
setInterval(newParachute.animate, newParachute.speed);
But this inside animate the window object--not the Parachute object.
To give the correct this to animate you can use the call method like this:
var newParachute = new parachute();
setInterval(function(){newParachute.animate.call(newParachute);}, newParachute.speed);
(3) You need to deal with clearing previously drawn images or they will still show on your canvas.
The code:
function CreateAndAnimateEnemyImg() {
var enemy = new Image();
enemy.src = 'enemy.jpg';
enemy.class = 'Enemy';
enemy.width = '30px';
enemy.height = '30px';
document.body.appendChild(enemy);
enemy.onload = function () {
alert('2. Image has fully loaded.');
$('.Enemy').animate({ 'right': '+=20px' });
}
}
$("#Start").click(function () {
CreateAndAnimateEnemyImg();
});
The weird behavior is that the alert is raised but no image is shown, nor the animation is working. Any help please?
Change your code:
enemy.className = 'Enemy';
enemy.width = '30'; // no px needed
enemy.height = '30';
http://jsfiddle.net/UqcqN/
You have two mistakes: if you set width property you don't have to provide units. And you should set className property instead of class.
It is also recommended to set src after onload handler.
You have to enemy.src = 'enemy.jpg'; AFTER you define: enemy.onload.
i think no need for giving string kind of 'px';
rtefer this http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_img_height
here is the complete demo Fiddle
function CreateAndAnimateEnemyImg() {
var enemy = new Image();
enemy.src = 'http://media.steampowered.com/apps/440/icons/icon_dueling_large.14fd9f2da0f24b2dfaac37d1600c821ddb6d3456.png';
enemy.class = 'Enemy';
enemy.width = '130';
enemy.height = '130';
document.body.appendChild(enemy);
enemy.onload = function () {
alert('2. Image has fully loaded.');
$('.Enemy').html(enemy);
console.log(enemy);
$('.Enemy').animate({ 'right': '+=20px' });
}
}
$("#Start").click(function () {
CreateAndAnimateEnemyImg();
});
have an object of a class Abon and then i want this object to move around the page.
a = new Abon();
a.init();
a.move();
the method move() contains:
function abon_move () {
var x = this.x;
var y = this.y;
var direction_x = Math.random()*5 - 5;
var direction_y = Math.random()*5 - 5;
var x_new = x + direction_x * this.movement_rate;
var y_new = y + direction_y * this.movement_rate;
console.log(x_new+" "+y_new)
$(".abonent."+this.id).animate( {
left:+x_new,
top:+y_new
}, 'slow', "linear", function() { this.move() });
}
All i want is that the method move (represented as function abon_move()) repeated again and again, after the animate stops. But the problem is that this.move() shown in callback has no connection to my object, because this in that place points to the HTML element, selected by jQuery.
UPD:
function Abon(id) {
...
this.move = abon_move;
...
}
Abon.prototype.move = abon_move;
And the actual method is the same, but with no callback in animate
then i try doing the following:
setInterval( a[0].move , 300); //doesn't work - says `this` members are undefined
setInterval( a[0].move() , 300); //works only one time and stops
Thank you for any help!
Try this :
function abon_move () {
var x = this.x;
var y = this.y;
var class = this;
...
}
Then, inside your jQuery animate, your can refer to your class using the variable class
Wrap the function abon_move() in a setTimeout call, as such: setTimeout(abon_move, 300); so it will run every 300 ms.