-1

I'm new to Ractive.js and although it's been ridiculously easy to learn I'm hung up on how to implement the one feature I really want out of it. All of the examples in both the documentation and tutorials for Ractive.extend() involve adding custom methods inline whereas I want it to add instances of a class I have already defined in another file. My markup has a #with section containing several canvas elements where the id and several CSS values are all mustaches. In order to avoid replicating code and store all my data in one place, I want the same data to also be used to instantiate an object of my custom class for each canvas element and then be able to call methods from it in response to event proxies. In other words something like this, although I don't think it's the correct syntax:

EDIT: Feel free to answer in react.js instead. I'm learning both frameworks at once, but think JXS might make this easier to implement. And the code sample should be simple enough for people only familiar with react to understand.

var CanvasAnimation = Ractive.extend(){
    //do I need to specify a template here?
    var myCustomClass =  
        new customClass(this.id, this.width, this.height, this.animationURL);
    myCustomClass.setFrame(0);

    /* or is something like this better? may require updating my selector...
    var myCustomClass = new customClass();
    oninit: function() {
        myCustomClass(this.id, this.width, this.height, this.spriteSheetURL);
        myCustomClass.setFrame(0);
    };
    */
};

var canvasAnimation = new CanvasAnimation({
    el: '#container',
    template: '#template',
    data: { 
        //data for each canvas element goes here
        canvas1: {
            id: ,
            width: ,
            height: ,
            left: ,
            animationURL: 
        }
    }
});

canvasAnimation.on( 'setFrame', function ( event ) {
    //scale mouseY and call customClass method
    var offsetY = event.clientY - this.getBoundingClientRect().top; //is this right?
    var relY = offsetY/this.height;
    this.myCustomClass.setFrame(relY);
});
Sophia Gold
  • 756
  • 1
  • 8
  • 18

1 Answers1

1

This is probably the best way:

var CanvasAnimation = Ractive.extend() {
    oninit: function() {
        this.get('canvases').forEach(function (canvas) {
            var myCustomClass = new customClass(canvas.id, ...);
            myCustomClass.setFrame(0);
        });

        this.on('setFrame', function () { ... });
    };
};

To answer your question about specifying template - you don't have to. All options for Ractive.extend() are optional and only act as default values. However, if you specify it in Ractive.extend() you won't have to specify it on initialization.

Martin Kolárik
  • 721
  • 5
  • 7
  • I'm confused about part of this. When you instantiate it you pass this.get('canvas1.id') as the first argument, but I need it to instantiate an instance for *every* canvas object. I'm going to store the data in an array and I need this to instantiate not only canvas1, but canvas2...canvas100, etc. Also, if I call this.on() in Ractive.extend() will it still be able to pick up event properties (like clientY) and builtin methods of the element like getBoundingClientRect()? – Sophia Gold May 08 '16 at 23:34
  • I just want to be sure because the point of this is to instantiate a distinct object for *each* canvas I define in my data array and then to run that event proxy for each one individually, so when the mouse passes over the first or second or third canvas it should parse data from that specific event call and element to pass to that canvas's object's setFrame() method. Thanks! – Sophia Gold May 08 '16 at 23:34
  • That was just an example. If you have multiple canvases, you can store them in an array, and then instantiate your custom class using an Array#forEach loop. `this` inside event handlers points to the Ractive instance, but you can get the event properties (including the node) via `this.event`. – Martin Kolárik May 09 '16 at 20:14
  • I already have them stored in an array, but that's obviously not accessible from inside Ractive.extend(). So in your example I can't just wrap the first two lines inside oninit in data.forEach(function(){} because it has no idea what "data" is... – Sophia Gold May 10 '16 at 04:48
  • Thanks, that did it! But now it's throwing errors whenever I try to call methods of the canvases, both in the event handler in my code example (this.getBoundingClientRect is not a function) and in my animation class (this.canvas.getContext is not a function). Any ideas? If not I should maybe open a new question :( – Sophia Gold May 10 '16 at 14:19
  • Yes. As I mentioned earlier, `this` points to the Ractive instance. You need to use `this.event.node.getBoundingClientRect()`. If you run into any more problems, please open a new question and mark this question as answered. – Martin Kolárik May 10 '16 at 14:24
  • Yup, going to do that. Reread that docs on event, but still clearly not understanding something about how Ractive handles scope in general. Thanks for your help here, Martin! – Sophia Gold May 10 '16 at 14:49