john
john

Reputation: 13

Javascript - calling a method from inside an object (must be simple solution)

Okay guys, I'm sure this has a very simple solution but my searches are turning up nothing and I'm certain I am misunderstanding something very simple.

All I want to do is create an object that contains 2 methods, say for example initialise() and zoom(), at the end of initialise I want to call the zoom method, initialize sets instance variables like so 'this.width = 100', the problem is I cant call zoom() from intialise() if I declare zoom like so

this.zoom = function() {...};

if I declare it like this:

function zoom() {...};

I can call it from initialize but when I try and use the instance variables they come back as undefined, I also tried defining the method as a prototype but that has the same problem as the first method, when I call them from outside the object everything works as expected, however when I try to call the method from another method firebug just tells me the method does not exist.

As I said Im sure there is a simple explanation to do, please see the source code listing below for more details, any help greatly appreciated, thanks.

I'm sure more experienced people will see a whole host of problems in this code, it is very much a learning exercise to try and learn oop in javascript (which is extremely odd if you don't mind me saying) but if possible please lets just deal with the problem at hand and not get sidetracked on other issues, no doubt I shall return with them in another thread.

function maplocation(x, y, width, height, text, id, filename, from, to, folder)
{
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.text = text;
    this.id = id;
    this.canvasID = id + "canvas";
    this.containerID = id + "container";
    this.ctx;
    this.isZoomed = false;
    this.filename = filename;

    this.addLocation = function(element)
    {
        if(supports_canvas())
        {
            // insert location html
            var returnHTML = 
            '<div id="'+this.containerID+'" style="z-index:5; position:absolute; top:' + this.y + 'px; left:' + this.x + 'px">'+
                '<canvas id="' + this.canvasID + '" width="' + this.width +'" height="' + this.height + '" style="position:absolute; top:0px; left:0px">' +
                '</canvas>' +
                '<div id="' + this.id + '" style="text-align:center; padding:15px; position:absolute; top:0px; left:0px; width:' + (this.width - 30) + 'px; height:' + this.height + 'px; cursor:pointer">' +
                    text +  
                '</div>' +
            '</div>';

            $("#"+element).append(returnHTML);

            // draw into canvas
            this.ctx = document.getElementById(this.canvasID).getContext("2d");
            this.ctx.strokeStyle = "rgb(0, 0, 0)";
            this.ctx.fillStyle = "rgba(255, 255, 255, 0.65)";
            this.ctx.lineWidth = 2.2;
            this.roundRect(this.ctx, 5, 5, this.width-10, this.height -10, 15);

            // attach events
            var e = document.getElementById(this.containerID);
            e.addEventListener("click", this.onClick, false);
        }
    }

    this.zoomIn = function()
    {
        alert(this.filename); // THIS IS THE PROBLEM, I WANT TO ACCESS INSTANCE VARIABLE FROM THIS FUNCTION
        $("#theGarden").jsMovie("destroy");

        $('#theGarden').jsMovie({
            sequence: filename,
            from: from,
            to: to,
            folder : folder,  
            showPreLoader : false,
            repeat : false,
            fps: 10,
            loadParallel: 1,
            width: 960,
            height: 529
        });
        $("#theGarden").jsMovie('play',0,15);
        //$("#theGarden").jsMovie("gotoFrame",to);
        //$("#theGarden").jsMovie("pause");
    }

    this.onClick = function(f)
    {
        this.zoomIn(); // THIS IS THE INTERNAL CALL THAT FAILS
    }

    function supports_canvas() 
    {
        return !!document.createElement('canvas').getContext;
    }

    this.roundRect = function(ctx, x, y, w, h, r) 
    {
        var mid = w/2;
        var baseOff = 10;
        var offh = h - baseOff;

        ctx.beginPath();
        ctx.moveTo(x + r, y);
        ctx.lineTo(x + w - r, y);
        ctx.quadraticCurveTo(x + w, y, x + w, y + r);
        ctx.lineTo(x + w, y + offh - r);
        ctx.quadraticCurveTo(x + w, y + offh, x + w - r, y + offh);

        ctx.lineTo(x + mid + 10, y + offh);
        ctx.lineTo(x + mid, y + h);
        ctx.lineTo(x + mid - 10, y + offh);
        ctx.lineTo(x + r, y + offh);

        ctx.quadraticCurveTo(x, y + offh, x, y + offh - r);
        ctx.lineTo(x, y + r);
        ctx.quadraticCurveTo(x, y, x + r, y);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();

    }
}

Upvotes: 1

Views: 534

Answers (1)

Pointy
Pointy

Reputation: 413712

If you're setting up that "onClick" function as an event handler, with code something like this:

  someElement.onclick = thing.onClick;

then the problem is that when an actual call to the function is made (when an event occurs), the browser won't be able to arrange for this to be the right thing. Thus, when you set up the event handler, you have to make sure you bind a function that does know the context:

  someElement.onclick = function() { thing.onClick(); };

edit — Oh ok, now I see the code that binds the handler. That should look like this:

        // attach events
        var e = document.getElementById(this.containerID);
        var thisObject = this;
        e.addEventListener("click", function() { thisObject.onClick(); }, false);

Upvotes: 1

Related Questions