JavaScript object inheritance issues - javascript

Hi please be patient with me. I am a PHP developer entering the world of javaScript. Now I'm building a grid that will contain blocks of different size. I want a base block with all the methods on it and then other blocks that extend this (to use its methods) but with different properties. I have done a lot of reading but dont seem to be able to find a consistent method. I have put together some code i though would work but it doesn't. SmallBlock in the example has its own properties but none of Blocks properties
// Simple extend function to add for creating object inheritance
function extend(Child, Parent) {
var Temp = function(){
Temp.prototype = Parent.prototype;
Child.prototype = new Temp();
Child.prototype.constructor = new Child();
}
}
//__________________________________________________
// ## OBJECT DECLARATIONS ##
//__________________________________________________
//__________________________________________________
// ## BLOCK ##
// Base object representing a block/tile in the grid
var Block = function(){
// The X position block
this.positionX = 0;
// The Y position block
this.positionY = 0;
// The height of the block
this.height = 0;
// The width of the block
this.width = 0;
// The horizontal orientation of a block
this.blockHorizontalOrientation = null;
// The vertical orientation of a block
this.blockVerticalOrientation = null;
// Method to set the width of a block
this.setWidth = function(width){
this.width = width;
};
// Method to set the height of a block
this.setHeight = function(height){
this.height = height;
};
// Method to get the width of a block
this.getWidth = function(){
return this.width;
};
// Method to get the height of a block
this.getHeight = function(){
return this.height;
};
// Method to set the X position of a block (in the grid)
this.setPosX = function(posX){
this.positionX = posX;
};
// Method to set the Y position of the block (in the grid)
this.setPosY = function(posY){
this.positionY = posY;
};
// Method to get the Y position of the clock
this.getPosY = function(){
return this.positionY;
};
// Method to get the X position of the clock
this.getPosX = function(){
return this.positionX;
};
// Method to get the horizontal orientation
this.getHOrientation = function(){
return this.blockHorizontalOrientation;
};
// Method to get the vertical orientation
this.getVOrientation = function(){
return this.blockVerticalOrientation;
};
// Method to get the horizontal orientation
this.setHOrientation = function(hOren){
this.blockHorizontalOrientation = hOren;
};
// Method to get the vertical orientation
this.setVOrientation = function(vOren){
this.blockVerticalOrientation = vOren;
};
}
//__________________________________________________
// ## SMALL BLOCK ##
// object representing a small block/tile in the grid -- extends Block
var BlockSmall = function(){
// The X position block
this.positionX = 0;
// The Y position block
this.positionY = 0;
// The height of the block
this.height = 1;
// The width of the block
this.width = 1;
// The horizontal orientation of a block
this.blockHorizontalOrientation = null;
// The vertical orientation of a block
this.blockVerticalOrientation = null;
};
// EXTENDING BLOCK
extend(BlockSmall, Block);
Please can somebody review this code and help by advising what it is i am doing wrong. Again please be patient with me if I am miles out. This is all brand new concepts to me.

Well, this should work for inheriting:
function extend(Child, Parent) {
Child.prototype = new Parent();
Child.constructor = Child;
}
In your code, you just define a function inside extend that never gets called.

Related

Add variable property new value to previous value (javascript)

Good afternoon. Is it possible to add a new object property value to its previous value?
I have tried the following code but browser returns "Maximum call stack size exceeded". The property translate will be used to drag a chart horizontally. It will shift the data range of an array that will be painted on the canvas chart. Kind regards.
function drawChart() {
.
.
.
tickerData = [..., ..., ...];
dataLength = tickerData.length;
barSpace = Number(localStorage.getItem("barspace"));
barWidth = (0.7 * barSpace).toFixed(1);
rightSpan = 3 * barSpace;
barStrokeWidth = 1;
if(!(dataLength - dragCanvas.translate() > dataLength)) {
dataLength = dataLength - dragCanvas.translate();
}
else {
dataLength = dataLength;
}
.
.
.
}
var dragCanvas = {
isTrue : false,
drag : [0, 0],
translate : function() {
return this.translate() + Math.ceil((this.drag[1] - this.drag[0])/barSpace);
}
};
function updateChartPaint(e) {
var pointerX = e.clientX;
var pointerY = e.clientY;
if(!dragCanvas.isTrue) {
dragCanvas.drag[0] = pointerX;
dragCanvas.drag[1] = pointerX;
}
else {
dragCanvas.drag[1] = pointerX;
$("#chartCanvas").empty();
drawChart();
}
}
document.addEventListener("mousemove", updateChartPaint, false);
document.getElementById("chartCanvas").onmousedown = function() {
dragCanvas.isTrue = true;
};
document.getElementById("chartCanvas").onmouseup = function() {
dragCanvas.isTrue = false;
};
You are calling this.translate() inside of the translate function so it goes into an infinite loop calling itself until eventually the call stack is exceeded.
From the way translate is called it looks like the function should be defined like this instead:
translate : function() {
const newTranslate = this.oldTranslate + Math.ceil((this.drag[1] - this.drag[0])/barSpace);
this.oldTranslate = newTranslate;
return newTranslate;
}
oldTranslate: 0
I assume that barSpace is declared outside of the function and will be a valid value. It seems to be set from localStorage but if it does not exist, then Number(localStorage.getItem("barspace")) will be zero and the return value from translate will be Infinity. Is that intended?
Also updateChartPaint sets a variable called pointerY but never uses it. Is it correct that dragging in the Y-axis is ignored and only changes in the X-axis matters?

Removing properties which are not owned or inherited

This is my code.
function Material() {
this.id = null;
}
function Box() {
// Inherit Material props
Material.call(this)
// Define own props
this.width = null;
this.height = null;
this.weight = null;
}
var box = new Box();
// Setting values to Box props
box.id = 12;
box.width = 250;
box.height = 350;
box.weight = '10kg';
// Not its property
box.color = 'red';
// TODO: Passing box variable via function which will return new object of Box without color property
console.log(box);
// {
// 'id': 12,
// 'width': 250,
// 'height': 350,
// 'weight': '10kg',
// }
So basically at some point I want to get rid of color property that got set on box object (which is not the property of Box Class).
I don't want to individually delete such properties since there can be many. I have no way to find out which properties to delete. But I just know which properties to keep (Its own & inherited).
I am using lodash here. I tried _.forIn alongside _.defaults but of no help.
Thanks
try these:
var diff = _.difference(_.keys(box), _.keys(new Box()));
var clear = _.omit(box, diff);
console.log(clear);
clear - is a copy of box object with initial collection of properties
You can create a dummy Box object, loop through your object's properties and check, whether or not dummy object contains it:
function Material() {
this.id = null;
}
function Box() {
// Inherit Material props
Material.call(this)
// Define own props
this.width = null;
this.height = null;
this.weight = null;
}
function removeAdditionalProperties(obj) {
var dummy = new Box();
for (var key in obj) {
if (!dummy.hasOwnProperty(key)) {
delete obj[key]; // Or whatever you want to do with that prop
}
}
}
var box = new Box();
// Setting values to Box props
box.id = 12;
box.width = 250;
box.height = 350;
box.weight = '10kg';
// Not its property
box.color = 'red';
removeAdditionalProperties(box);
console.log(box);

EaselJs: Objects, Classes, and Making A Square Move

Although I have used Javascript extensively in the past, I have never used classes and objects in my programs. This is also the first for me using the HTML5 canvas element with an extra Javascript library. The library I'm using is EaselJS.
Short and sweet, I'm trying to make a square move with keyboard input, using object-oriented programming. I've already looked over sample game files, but I've never been able to properly get one to work.
The following is my classes script:
/*global createjs*/
// Shorthand createjs.Shape Variable
var Shape = createjs.Shape;
// Main Square Class
function square(name) {
this.name = name;
this.vX = 0;
this.vY = 0;
this.canMove = false;
this.vX = this.vY = 0;
this.canMove = false;
this.body = new Shape();
this.body.graphics.beginFill("#ff0000").drawRect(0, 0, 100, 100);
}
And below is my main script:
/*global createjs, document, window, square, alert*/
// Canvas and Stage Variables
var c = document.getElementById("c");
var stage = new createjs.Stage("c");
// Shorthand Create.js Variables
var Ticker = createjs.Ticker;
// Important Keycodes
var keycode_w = 87;
var keycode_a = 65;
var keycode_s = 83;
var keycode_d = 68;
var keycode_left = 37;
var keycode_right = 39;
var keycode_up = 38;
var keycode_down = 40;
var keycode_space = 32;
// Handle Key Down
window.onkeydown = handleKeyDown;
var lfHeld = false;
var rtHeld = false;
// Create Protagonist
var protagonist = new square("Mr. Blue");
// Set Up Ticker
Ticker.setFPS(60);
Ticker.addEventListener("tick", stage);
if (!Ticker.hasEventListener("tick")) {
Ticker.addEventListener("tick", tick);
}
// Init Function, Prepare Protagonist Placement
function init() {
protagonist.x = c.width / 2;
protagonist.y = c.height / 2;
stage.addChild(protagonist);
}
// Ticker Test
function tick() {
if (lfHeld) {
alert("test");
}
}
// Handle Key Down Function
function handleKeyDown(event) {
switch(event.keyCode) {
case keycode_a:
case keycode_left: lfHeld = true; return false;
case keycode_d:
case keycode_right: rtHeld = true; return false;
}
}
This is the error I get in the Developer Tools of Chrome:
Uncaught TypeError: undefined is not a function
easeljs-0.7.0.min.js:13
In case you're wondering, the order of my script tags is the EaselJS CDN, followed by my class, followed by the main script file.
I would really like closure on this question. Thank you in advance.
I figured it out. I was adding the entire protagonist instance to the stage. I've fixed by adding the protagonist.body to the stage.

Animating canvas with a javascript constructor

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.

Canvas stroke text for every object in array but draw just one image

I am trying to draw small image on canvas and some text for every person which I have in array.
I am doing like this
function drawPersonsOnCanvas(canvas, persons) {
var workIcon = '../images/work.png';
var partyIcon = '../images/party.png';
var context = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;
// randomizePositions just put every object of array on random position inside canvas
persons = randomizePositions(persons, width, height);
for (var i in persons) {
var person= persons[i];
person['image'] = new Image();
person['image'].src = (person['type'] === 'work') ? workIcon: partyIcon;
person['image'].onload = function() {
context.drawImage(person['image'], person['x'], person['y']);
};
context.strokeText('person ' + person['status'], person['x'], person['y']);
}
}
and I always get all texts on map on good positions and just one image and x and y are different for all ( I have 5 persons in array, I tried and without onload but it doesn't work). Does anyone know what to change so I get one picture for every person?
By the time each onload is executed, your person variable has already been reassigned to the next element in persons.
So you need to create a new person variable inside onload.
To do this, add an index to your person[‘image’] that points to the correct person.
…
person['image'].index=i;
person['image'].src = (person['type'] === 'work') ? workIcon: partyIcon;
…
Then inside onload you can recreate the correct person:
var person=persons[this.index];
So your reworked code looks like this...and a Fiddle: http://jsfiddle.net/m1erickson/xms9B/
function drawPersonsOnCanvas(canvas, persons) {
var workIcon = '../images/work.png';
var partyIcon = //'../images/party.png';
var context = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;
// randomizePositions just put every object of array on random position inside canvas
persons = randomizePositions(persons, width, height);
for (var i in persons) {
var person= persons[i];
person['image'] = new Image();
person['image'].onload = function() {
var person=persons[this.index];
context.drawImage(person['image'], person['x'], person['y']);
context.strokeText('person ' + person['status'], person['x'], person['y']);
};
person['image'].index=i;
person['image'].src = (person['type'] === 'work') ? workIcon: partyIcon;
}
}

Categories

Resources