SitePoint Sponsor

User Tag List

Results 1 to 2 of 2
  1. #1
    SitePoint Member
    Join Date
    Jan 2004
    Location
    Houston, TX
    Posts
    10
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    'this' picking up anchor object on click event into function

    I've been trying to get the hang of the self-executing function/module pattern down as I've been working through some of the examples in The Art and Science of JavaScript, but I keep having an issue when I try to create a class. The issue I have is that when I attach an object method to an anchor click event, the 'this' object within the function picks up the anchor tag and not the function. I'm quite sure I'm mistaken, but I thought 'this' always took on the context of the containing function. Any help would be appreciated.

    Here's the code:
    Code:
    // Declare the Demo namespace. This is the only global variable.
    if (typeof Demo == "undefined" || !Demo) {
        var Demo = {};
    }
    Demo = function() {
        // Declare the base methods of the static
        // Demo library.
        return {
            // Public methods
            namespace:function() {
                var a=arguments, o=null, i, j, d;
                for (i=0; a[i]; i++) {
                    d=a[i].split(".");
                    o=Demo;
                    // Demo is implied, so ignore it if it is included.
                    for (j=(d[0] == "Demo") ? 1 : 0; d[j]; j++) {
                        o[d[j]]=o[d[j]] || {};
                        o = o[d[j]];
                    }
                }
                return o;
            },
            getTarget:function(e){
                var target = window.event ? window.event.srcElement : e ? e.target : null;
                if (!target){return false;}
                if (target.nodeName.toLowerCase() != 'a'){target = target.parentNode;}
                return target;
            },
            cancelClick:function(e){
                if (window.event){
                    window.event.cancelBubble = true;
                    window.event.returnValue = false;
                    return;
                }
                if (e){
                    e.stopPropagation();
                    e.preventDefault();
                }
            },
            addEvent:function(element, type, func, useCapture) {
                if (document.addEventListener) {
                    addEvent = function(element, type, func, useCapture) {
                        element.addEventListener(type, func, useCapture);
                        return true;
                    };
                } else if (document.attachEvent) {
                    addEvent = function(element, type, func) {
                        var r = element.attachEvent('on' + type, func);
                        return r;
                    };
                } else {
                    addEvent = function(element, type, func) {
                        element['on' + type] = func;
                    };
                }
                addEvent(element, type, func, useCapture);
            },
            cssjs:function(a,o,c1,c2) {
                switch (a){
                    case 'swap':
                        o.className=!that.cssjs('check',o,c1)?o.className.replace(c2,c1):o.className.replace(c1,c2);
                        break;
                    case 'add':
                        if(!that.cssjs('check',o,c1)){o.className+=o.className?' '+c1:c1;}
                        break;
                    case 'remove':
                        var rep=o.className.match(' '+c1)?' '+c1:c1;
                        o.className=o.className.replace(rep,'');
                        break;
                    case 'check':
                        return new RegExp("(^|\\s)" + c1 + "(\\s|$)").test(o.className)
                        break;
                }
            },
            getElementsByClassName:function(className, context) {
                var getEls;
                if (typeof document.evaluate == 'function') {
                    getEls = function(className, context) {
                        var els = [];
                        var xpath =
                            document.evaluate(
                                ".//*[contains(concat(' ', @class, ' '), ' "
                                + className + " ')]", context, null,
                                XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
                        for (var i = 0, l = xpath.snapshotLength; i < l; i++)
                            els.push(xpath.snapshotItem(i));
                        return els;
                    }
                } else {
                    getEls = function(className, context) {
                        var nodeList = context.getElementsByTagName('*');
                        var re = new RegExp('(^|\\s)' + className + '(\\s|$)');
                        return Array.filter(nodeList, function(node) {
                            return node.className.match(re) });
                    }
                }
                document.getElementsByClassName = function(className, context) {
                        context = context || document;
                        return getEls(className, context);
                }
                return document.getElementsByClassName(className, context);
            }
        };
    }();
    
    (function() {
        Demo.namespace("Drawing");
        Demo.Drawing.Canvas = function(name, height, width) {
            this._drawing = {};
            this._context = {};
            this._name = name ? name : "drawing";    // Declare a default value if no value is provided.
            this._height = height ? height : 400;    // Declare a default value if no value is provided.
            this._width = width ? width : 400;       // Declare a default value if no value is provided.
        };
        Demo.Drawing.Canvas.prototype = {
            name:function() {
                var a = arguments;
                if (!a) {return this._name;}
                this._name = a[0];
            },
            height:function() {
                var a = arguments;
                if (!a) {return this._height;}
                this._height = a[0];
            },
            width:function() {
                var a = arguments;
                if (!a) {return this._width;}
                this._width = a[0];
            },
            addCanvas:function() {
                // Create the graph canvas element.
                this._drawing = document.createElement("canvas");
                this._drawing.setAttribute("id", this._name);
                this._drawing.setAttribute("width", this._width);
                this._drawing.setAttribute("height", this._height);
                
                // Append the graph canvas to the body.
                document.body.appendChild(this._drawing);
                
                // Set the context.
                if (typeof this._drawing.getContext != "undefined") {
                    this._context = this._drawing.getContext("2d");
                }
            },
            resizeCanvas:function(height, width) {
                // Set the height and width.
                this._height = height ? height : this._height;
                this._width = width ? width : this._width;
    
                // Resize the graph. --Not sure why this isn't necessary.
                //this._canvas.setAttribute("height", this._height);
                //this._canvas.setAttribute("width", this._width);
            },
            clearCanvas:function() {
                this._context.strokeStyle = "#000000";
                this._context.clearRect(0, 0, this._height, this._width);
            },
            removeCanvas:function() {
                var parent = this._drawing.parentNode;
                parent.removeChild(this._drawing);
            },
            drawRect:function() {
                this._context.fillStyle = "#0066CC";
                this._context.fillRect(0, 0, 400, 400);
                this._context.clearRect(75, 75, 250, 250);
                this._context.strokeStyle = "#FF0000";
                this._context.strokeRect(150.5, 150.5, 100, 100);
            },
            drawCircle:function() {
                this._context.beginPath();
                this._context.arc(200, 100, 50, 0, 2*Math.PI, true);
                this._context.closePath();
                this._context.stroke();
            },
            drawPath:function() {
                this._context.beginPath();
                this._context.moveTo(150, 100);
                this._context.lineTo(200, 225);
                this._context.stroke();
            },
            drawTri:function() {
                this._context.beginPath();
                this._context.moveTo(150, 100);
                this._context.lineTo(200, 225);
                this._context.lineTo(250, 100);
                this._context.fillStyle = "#D3BEA5";
                this._context.fill();
                this._context.stroke();
            },
            drawIceCream:function() {
                this._context.beginPath();
                this._context.moveTo(150, 100);
                this._context.lineTo(200, 225);
                this._context.lineTo(250, 100);
                this._context.fillStyle = "#D3BEA5";
                this._context.fill();
                this._context.stroke();
                
                this._context.beginPath();
                this._context.arc(200, 100, 50, 0, Math.PI, true);
                this._context.fillStyle = "#FB6CF9";
                this._context.fill();
                this._context.closePath();
                this._context.stroke();
            },
            drawMeltingCone:function() {
                this._context.beginPath();
                this._context.moveTo(150, 100);
                this._context.lineTo(200, 225);
                this._context.lineTo(250, 100);
                this._context.fillStyle = "#D3BEA5";
                this._context.fill();
                this._context.stroke();
                
                this._context.beginPath();
                this._context.arc(200, 100, 50, 0, Math.PI, true);
                this._context.lineTo(160, 100);
                this._context.bezierCurveTo(170, 100, 180, 110, 180, 120);
                this._context.bezierCurveTo(180, 125, 172, 140, 185, 140);
                this._context.bezierCurveTo(198, 140, 190, 125, 190, 120);
                this._context.bezierCurveTo(190, 110, 200, 100, 210, 100);
                this._context.fillStyle = "#FB6CF9";
                this._context.fill();
                this._context.closePath();
                this._context.stroke();       
            }
        };
    })();
    
    // This is the application code in the form of a self-executing function.
    (function() {
        // Create the canvas element.
        var drawing = new Demo.Drawing.Canvas;
        alert("name: " + drawing.name() + ", height: " + drawing.height() + ", width: " + drawing.width());
        Demo.addEvent(window, 'load', drawing.addCanvas, false);
        // Resize the element from 400x400 (default) to 320x320.
        //drawing.resize(320, 320);  // Or drawing.height(320);drawing.width(320);drawing.resize;
        // Draw a rectangle when the 'Draw Rectangle' link is clicked.
        function addListeners() {
            var rectLink = document.getElementById("drawRect");
            Demo.addEvent(rectLink, 'click', drawing.drawRect, false);
            var circleLink = document.getElementById("drawCircle");
            Demo.addEvent(circleLink, 'click', drawing.drawCircle, false);
            var pathLink = document.getElementById("drawPath");
            Demo.addEvent(pathLink, 'click', drawing.drawPath, false);
            var triLink = document.getElementById("drawTri");
            Demo.addEvent(triLink, 'click', drawing.drawTri, false);
            var iceCreamLink = document.getElementById("drawIceCream");
            Demo.addEvent(iceCreamLink, 'click', drawing.drawIceCream, false);
            var meltingConeLink = document.getElementById("drawMeltingCone");
            Demo.addEvent(meltingConeLink, 'click', drawing.drawMeltingCone, false);
            var clearLink = document.getElementById("clearCanvas");
            Demo.addEvent(clearLink, 'click', drawing.clearCanvas, false);
        }
        Demo.addEvent(window, 'load', addListeners, false);
        // Remove the canvas.
        Demo.addEvent(window, 'unload', drawing.removeCanvas, false);
    })();

  2. #2
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    In a listener (function) for an event, this always refers to the element the event occurred on. That is, unless your name is Internet Explorer and you are using something called attachEvent. In the traditional model (element.onclick) and in the W3C model (addEventListener) this always refers to the element the event happened on.

    If you want to preserve a reference to your object you can use call() or apply(). However, your object should be available anyway so that you can just do Demo.method if you want a static method, or drawing.method if it's an instance of the object. In the latter case, the function run by the event would have to be in the right scope to access this instance of Demo.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •