Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 2 of 2
  1. #1
    New to the CF scene
    Join Date
    Mar 2009
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Unobtrusive classes & 'this'

    Hi, I'm trying to write an unobtrusive javascript class which makes it so that when you click in a textbox, a dropdown is shown next to it (it'll eventually become something like a predictive textbox).

    The problem I'm having is that I'm losing reference to the class whenever I give an element within it an event handler and 'this' is referring to the element that raised the event (as it should), but I want a reference to the class instance.

    My html
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Example</title>
        <script type="text/javascript" src="Global.js"></script>
        <script type="text/javascript" src="example.js"></script>
        <script type="text/javascript" src="ExampleClass.js"></script>
    </head>
    <body>
    
        <input type="text" value="" id="clickThis" />
        <select id="selectThis" style="display: none;">
            <option value="1">Value 1</option>
            <option value="2">Value 2</option>
            <option value="3">Value 3</option>
        </select>
        
    </body>
    </html>
    My javascript file for the page

    Code:
    addEvent(window, "load", initExample);
    
    function initExample()
    {
        var textbox = document.getElementById("clickThis");
        var dropdown = document.getElementById("selectThis");
    
        var test = new ExampleClass(textbox, dropdown);
    }
    My javascript class
    Code:
    function ExampleClass(textbox, dropdown) {
        this.textbox     = textbox;
        this.dropdown    = dropdown;
        
        addEvent(this.textbox, 'click', showDropdown);
        
        function showDropdown()
        {
            this.dropdown.style.display = "block";
        }
    }
    Gloal.js (its just John Resigs add and remove event functions)

    Code:
    function addEvent( obj, type, fn ) {
      if ( obj.attachEvent ) {
        obj['e'+type+fn] = fn;
        obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
        obj.attachEvent( 'on'+type, obj[type+fn] );
      } else
        obj.addEventListener( type, fn, false );
    }
    
    function removeEvent( obj, type, fn ) {
      if ( obj.detachEvent ) {
        obj.detachEvent( 'on'+type, obj[type+fn] );
        obj[type+fn] = null;
      } else
        obj.removeEventListener( type, fn, false );
    }
    Basically, when I say this.dropdown.display.. I want it to point at the classes .display property, not the actual textbox which raised the event.

    Thanks in advance for any help

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    27,649
    Thanks
    80
    Thanked 4,636 Times in 4,598 Posts
    The problem is, of course, that indeed the this can *ONLY* refer to the object which *raises* the event.

    And then your other problem is that you have no "connection" from those event-raising objects *to* your ExampleClass instances.

    An obvious answer would be to simply add a property to the textbox that refers to the ExampleClass object you created for it. But if I recall correctly, this does not work in all browsers.

    So another way would be to use an associative array to "map" the eventable-objects to the connected ExampleClass objects. And of course all arrays in JS are naturally associative arrays, so that's easy enough.

    I admit I've never tried using object references as the "keys" in a JS array, but there's a first time for everything:
    Code:
    var ExampleEventObjects = new Array( );
    
    ...
    function ExampleClass(textbox, dropdown) {
        this.textbox     = textbox;
        this.dropdown    = dropdown;
        addEvent(this.textbox, 'click', showDropdown);
        ExampleEventObjects(this.textbox) = this;
        
        function showDropdown()
        {
            ExampleEventObject(this).dropdown.style.display = "block";
        }
    }
    Utterly untested and never done anything like it, but seems to make sense to me. If it doesn't work with object references for keys, you could always use the object ID's instead and then have to use this.id to do the "lookup".


  •  

    Posting Permissions

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