Passing values into p5's canvas, instancing - javascript

Let's say I have several p5 canvases on one page, and I've chosen to use instancing to split them up. Because many of the methods will perform the same operations, I've made a superclass. It looks something like this:
var BasicCanvas = function(p) {
p.setup = function() {
p.createCanvas(100, 100);
p.background(0);
}
p.draw = function() {
}
}
I'll have to create a subclass and pass this into a new p5 object, like this:
var myP5 = new p5(BasicCanvas);
How should I go about creating a subclass of my super in such a way it can be passed into the p5 constructor function? My ideal code setup looks like:
var super = function(p) {
p.setup = function() { creation }
}
var sub1 = function(p) {
p.draw = function() { circles }
}
var sub2 = function(p) {
p.draw = function() { squares }
}
var myP5 = new p5(sub1);
var myP52 = new p5(sub2);
But coming from Java, I'm having some difficulty getting around the differences. Can you help?
Thank you!

var superFunction = function(p) {
p.setup = function() {
p.createCanvas(200, 150)
p.noStroke()
}
}
var sub1 = function(p) {
superFunction(p)
p.draw = function() {
p.background(50)
p.fill("blue")
p.rect(20,20,50,50)
}
}
var sub2 = function(p) {
superFunction(p)
p.draw = function() {
p.background(100)
p.fill("red")
p.rect(20,20,50,50)
}
}
var myP5 = new p5(sub1)
var myP52 = new p5(sub2)
Note: super is a reserved keyword in Javascript

Related

JS "... is not a constructor" mystery

I'm confused at this point and I did searched for a solution but couldn't quite find the one answers my situation. Here is the code block I'm having trouble with
this.render = function() {
this.$el.html(Handlebars.compile($("#home-tpl").html()));
itemListView = new ItemListView();
itemListView.setItems(items);
$('.content', this.$el).html(itemListView.$el);
return this;
};
It runs flawlessly the first time. But when I navigate back to this from other page
itemListView = new ItemListView();
section gives me a "ItemListView is not a constructor" error!
This is what ItemListView looks like
var ItemListView = function () {
var service = new DataService();
var items = [];
this.initialize = function() {
this.$el = $('<div/>');
this.render();
};
this.viewAll = function() {
items = service.viewall();
this.render();
}
this.setItems = function(list) {
items = list;
this.render();
}
this.render = function() {
this.$el.html(Handlebars.compile($("#item-list-tpl").html())(items));
return this;
};
this.initialize();
}
Now why would it run the first time but not the next time?

Is it possible to unit-test this javascript structure?

Given the following JavaScript structure:
addClickEvent: function() {
element.addEventListener('click', function() {
self.a();
self.b();
});
},
Is it possible to assert that a() and b() have been called without refactoring out the anonymous function or editing it's contents?
Assuming the self in your code is the window.self property.
You could do something like this:
function element_onclick_callsAandB() {
// Arrange
var aCalled = false;
var bCalled = false;
var element = ...;
var origA = self.a;
var origB = self.b;
self.a = function() {
aCalled = true;
origA();
};
self.b = function() {
bCalled = true;
origB();
};
try {
// Act
element.click();
// Assert
assertTrue(aCalled);
assertTrue(bCalled);
}
finally {
self.a = origA;
self.b = origB;
}
}

Cannot reference method on Javascript object

I'm writing a version of Pong in Javascript. I have a Game object and I'm using the prototype property to define methods on it. I'm getting the following error: "Undefined is not a function". It is being thrown in the Game.prototype.step function so this.update is undefined in there. Here's the code for the Game object:
(function(root) {
var Pong = root.Pong = (root.Pong || {});
var Game = Pong.Game = function() {
this.canvas = document.getElementById('canvas');
this.canvas.width = 800;
this.canvas.height = 400;
this.context = canvas.getContext('2d');
this.maxStartSpeed = 10;
this.keysDown = {};
this.player2 = new Pong.Player({'player': 2});
this.player1 = new Pong.Player({'player': 1});
this.ball = new Pong.Ball(400, 200);
}
Game.prototype.update = function() {
this.player1.update();
this.player2.update();
this.ball.update(player1.paddle, player2.paddle);
};
Game.prototype.render = function() {
this.context.fillStyle = "#bdc3c7";
this.context.fillRect(0, 0, width, height);
this.player1.render();
this.player2.render();
this.ball.render();
};
Game.prototype.animate = function(callback) {
window.setTimeout(callback, 1000/60)
};
Game.prototype.step = function() {
this.update();
this.animate(this.step);
};
window.addEventListener("keydown", function (event) {
Game.keysDown[event.keyCode] = true;
});
window.addEventListener("keyup", function (event) {
delete Game.keysDown[event.keyCode];
});
window.onload = function() {
document.getElementById('canvas-container').appendChild(canvas);
game = new Game();
game.animate(game.step);
};
})(this);
The setTimeout is going to change the scope. To maintain the proper scope, you need to use bind
Change
this.animate(this.step);
to
this.animate(this.step.bind(this));
You need to do the same thing with the other animate calls.

Extend prototype with another prototype

How can I extend prototype A with prototype B, so whenever I call prototype A, both will be executed?
var Helper = function() {
}
Helper.prototype.resizer = function() {
$('body').append(' Window resized ');
}
var Something = function() {
// Extend Helper.resizer with Something.anything
// extend(Helper.resizer, this.anything);
}
Something.prototype.anything = function() {
$('body').append(' Run this on resize to ');
}
var help = new Helper();
var some = new Something();
$(window).on("resize", function(){
help.resizer();
});
Made an example at codepen:
http://codepen.io/robbue/pen/892c8f61e1b5a970d6f694a59db401a6
jQuery allowed, or just vanilla.
I don't really understand your question because prototypes are not executed, but I think you want something like this:
var Helper = function() {}
Helper.prototype.resizer = function() {
$('body').append(' Window resized ');
}
var Something = function(h) {
var oldresizer = h.resizer,
that = this;
h.resizer = function() {
var res = oldresizer.apply(this, arguments);
that.anything();
return res;
};
}
Something.prototype.anything = function() {
$('body').append(' Run this on resize to ');
}
var help = new Helper();
new Something(help);
$(window).on("resize", function(){
help.resizer();
});
or that:
function Helper() {}
Helper.prototype.resizer = function() {
$('body').append(' Window resized ');
}
function Something() { // inherits Helper
Helper.apply(this, arguments);
}
Something.prototype = Object.create(Helper.prototype);
Something.prototype.anything = function() {
$('body').append(' Run this on resize to ');
};
Something.prototype.resizer = function() {
Helper.prototype.resizer.call(this);
this.anything();
};
var help = new Something(help);
$(window).on("resize", function(){
help.resizer();
});

How can I add OOP to these JS functions?

I know this may seem like a repeated question, but I am currently stuck as to the best way to approach this, limited mostly by my lack of knowledge. Thus I am here to learn.
I am trying to do some simple OOP with JavaScript but coming from C# I am having a few issues with how to best solve this problem. Below I have four "Classes"; DisplayEngine, DisplayElement, Box, and Grid.
I would like Box and Grid to inherit DisplayElement, and be able to call the base functions in each of their respective functions. Almost like super.call() or something.
How would you best approach this?
var DisplayEngine = function() {
this.elements = [];
this.add = function(element) {
this.elements.push(element);
};
this.update = function() {
this.elements.forEach(function(element) {
element.update();
})
};
this.draw = function() {
this.elements.forEach(function(element) {
element.draw();
})
};
};
var DisplayElement = function() {
this.update = function() {
console.log('DisplayElement update');
};
this.draw = function() {
console.log('DisplayElement draw');
};
};
var Box = function() {
this.update = function() {
console.log('Box update');
// call DisplayElement.update()
};
this.draw = function() {
console.log('Box draw');
// call DisplayElement.draw()
};
};
var Grid = function() {
this.update = function() {
console.log('Grid update');
// call DisplayElement.update()
};
this.draw = function() {
console.log('Grid draw');
// call DisplayElement.draw()
};
};
$(function() {
var displayEngine = new DisplayEngine();
var box = new Box();
var grid = new Grid();
displayEngine.add(box);
displayEngine.add(grid);
displayEngine.update();
displayEngine.draw();
});
Here is a way to do it with prototype, each "class" need to be in his own file, the important part is Grid.prototype = new DisplayElement(); This allow you to call function from the DisplayElement in Grid:
DisplayEngine.js
function DisplayEngine() {
this.elements = [];
}
DisplayEngine.prototype.add = function(element) {
this.elements.push(element);
}
DisplayEngine.prototype.update = function() {
this.elements.forEach(function(element) {
element.update();
})
}
DisplayEngine.prototype.draw = function() {
this.elements.forEach(function(element) {
element.draw();
})
}
DisplayElement.js
function DisplayElement() {
}
DisplayElement.prototype.updateElement = function() {
console.log('DisplayElement update');
}
DisplayElement.prototype.drawElement = function() {
console.log('DisplayElement draw');
}
Box.js
function Box() {
}
Box.prototype = new DisplayElement();
Box.prototype.update = function() {
console.log('Box update');
this.updateElement();
}
Box.prototype.draw = function() {
console.log('Box draw');
this.drawElement();
}
Grid.js
function Grid() {
}
Grid.prototype = new DisplayElement();
Box.prototype.update = function() {
console.log('Grid update');
this.updateElement();
}
Box.prototype.draw = function() {
console.log('Grid draw');
this.drawElement();
}
Main.js
$(function() {
var displayEngine = new DisplayEngine();
var box = new Box();
var grid = new Grid();
displayEngine.add(box);
displayEngine.add(grid);
displayEngine.update();
displayEngine.draw();
});
To just answer to your question, declare your objects such as :
function DisplayElement() {};
DisplayElement.prototype.update = function() {
console.log('DisplayElement update');
};
DisplayElement.prototype.draw = function() {
console.log('DisplayElement draw');
};
// ...
// Now, instanciation :
var myElement = new DisplayElement();
Then, for inheritance :
function Box() {
DisplayEngine.call(this, arguments); // Call the super constructor
}
Box.prototype = Object.create(DisplayEngine.prototype); // "Apply" the inheritance
Box.prototype.constructor = Box; // Redefine the constructor to Box because it was overriden by the previous line
I disagree about those saying that you doesn't need "classes" in Javascript. In implementations such as Node.js which will handle datas must have, in my opinion, classes. It's easier (always in my opinion) to read, maintain, and use.
You can use the prototypal style like what Shryme explained, or you can use a library that mimcs the classical oop style in javascript, check Classing{js} : http://www.classingjs.co.nf/

Categories

Resources