So if I'm using Ractive.extend() to instantiate objects of a custom class then how would I go about referring to DOM elements inside that class? I obviously can't use document.getElementById() as usual since the DOM hasn't been rendered yet and passing Ractive.findComponent() to my constructor returns "Ractive.findComponent is not a function." What I want to do is something like this:
class myClass {
constructor(id /*,...*/) {
this.element = document.getElementById(id); //how do I do this??
};
};
var Extended = Ractive.extend( {
oninit() {
var myObject = new myClass(id /*,...*/);
this.set({myObject});
}
});
var ractiveExtended = new Extended({
el: document.body,
template: '#template',
data: { id: myId}
});
ETA: This doesn't work either...
class myClass {
constructor(id /*,...*/) {
this.element = document.getElementById(id);
};
};
var Extended = Ractive.extend( {
onrender() {
var myObject = new myClass(id /*,...*/);
this.set({myObject});
}
});
var ractiveExtended = new Extended({
el: document.body,
template: '#template',
data: { id: myId}
});
And neither does this...
class myClass {
constructor(id /*,...*/) {
this.element = id;
this.element.innerHTML = 'Hello world!';
};
};
var Extended = Ractive.extend( {
onrender() {
var myObject = new myClass(document.getElementById(id) /*,...*/);
this.set({myObject});
}
});
var ractiveExtended = new Extended({
el: document.body,
template: '#template',
data: { id: myId}
});
EDIT: Full running example available at: http://jsbin.com/vuziyepeku/edit?html,js,output
I would encapsulate each CanvasSprite
in it's own component:
const CanvasSpriteComponent = Ractive.extend({
template: '#sprite',
// Using onrender, not oninit, because we need DOM canvas node
onrender(){
const canvas = this.find('canvas');
const repeater = this.get('repeater');
var sprite = new CanvasSprite(canvas, repeater.width, repeater.height, repeater.spriteSheetURL, repeater.rows, repeater.columns, repeater.totalFrames);
sprite.left = repeater.left; //add variables *not* in the constructor
sprite.setFrame(0);
this.on('setFrame', function (event) {
var offsetY = event.original.clientY - event.node.getBoundingClientRect().top;
var relY = offsetY/sprite.height;
sprite.setFrame(relY);
});
}
});
Then use it in the main instance:
var CanvasAnimation = Ractive.extend( {
template: '#animation',
components: {
'canvas-sprite': CanvasSpriteComponent
}
});
var canvasAnimation = new CanvasAnimation({
el: 'main',
data: { repeaters: repeater }
});
Arguably it makes more sense for your CanvasSprite
class to take a canvas node because then it is no longer tied to how that node is located (currently document.getElementById
).
If you're not willing to change that class at all, you just need to make up a unique id (or use the index if the repeater collection is not going to mutate). In this case I'm reusing the component's unique id:
const CanvasSpriteComponent = Ractive.extend({
// ...
onrender(){
const canvas = this.find('canvas');
canvas.id = `canvas-${this._guid}`
const repeater = this.get('repeater');
var sprite = new CanvasSprite(canvas.id, repeater.width, repeater.height, repeater.spriteSheetURL, repeater.rows, repeater.columns, repeater.totalFrames);
sprite.left = repeater.left; //add variables *not* in the constructor
sprint.setFrame(0);
this.on('setFrame', function (event) {
var offsetY = event.original.clientY - event.node.getBoundingClientRect().top;
var relY = offsetY/sprite.height;
sprite.setFrame(relY);
});
}
});