Titanium Community Questions & Answer Archive

We felt that 6+ years of knowledge should not die so this is the Titanium Community Questions & Answer Archive

Javscript scope and event handlers

Hi all,

I think I am probably doing something wrong, and would be grateful for any advice.

I have a 'class' that looks something like this:

function MyClass() {
    this.myFunction = function() {
        // Some code here.
    }

    this.myOtherFunction = function() {
        // Some more code here.
    }
}

which I use like this:

var myThing = new MyClass();
myThing.myFunction();

in 'myFunction' I add an event listener to an animation (although it could be anything), which references 'myOtherFunction':

    this.myFunction = function() {
    // Some code here.

    someAnimation.addEventListener('complete', this.myOtherFunction);
}

This all works fine. However, when 'myOtherFunction' is called the context has changed (to that of the animation I think?), so 'this' no longer refers to the original instance of myClass. Is it possible to do this in such a way that myOtherFunction is 'aware' of the original context?

In this particular case I can get around it, in that myThing is effectively global, but this seems less than optimal.

Any advice would be greatly appreciated! I realise this isn't a strictly Titanium-based query, but figured it's almost certainly something others have run into. My Javascript knowledge is is not as developed as it could be!

Thanks,

Toby

— asked September 30th 2010 by Toby Mathews
  • javascript
0 Comments

2 Answers

  • I'm having the same kind of problem. My class object is going out of scope and I cant work out why.

    I have a GUI class that constructs a form. The Form has a button that fires an event to open a new window in the current tab. The new window is created via another class and this new window/class collects user input and stores it as instance variables that can be accessed from the first window… The instance variables are fine inside the second class but come back blank when access from outside the class.
    Here is some code.

    class 1

    function searchTable()
    {
        this.mode = 'buy';
        this.sub = '';
        this.ssubs = false;
        this.minPrice = '';
        this.maxPrice = '';
    
        this.getPriceRow = function() {
            // Create row
            var row = Ti.UI.createTableViewRow({
                height: 40,
                backgroundColor: '#ffffff',
                hasChild: true, // Add arrow to right of row
                selectionStyle: Titanium.UI.iPhone.TableViewCellSelectionStyle.NONE
            });
    
            // Create label
            var label = Ti.UI.createLabel({
                text: 'Price Range',
                top: 10,
                left: 10,
                height: 'auto',
                color: '#000000',
                textAlign: 'left',
                font: { fontSize: 15 }                
            });
    
            // Create range
            var range = Ti.UI.createLabel({
                text: 'Any',
                top: 10,
                right: 10,
                height: 'auto',
                color: '#6d6e71',
                textAlign: 'right',
                font: { fontSize: 15 }            
            });
    
            // Set price range
            row.addEventListener('click', function(e) {
                var prt = new priceRangeTable();
    
                var table = prt.getTable();
    
                // Create button
                var button = Ti.UI.createButton({
                    title:'Done',
                    width: 200,
                    height: 35,
                    left: 'auto',
                    right: 'auto',
                    bottom: 5,
                    enabled: true,
                    style: Ti.UI.iPhone.SystemButtonStyle.BORDERED
                });
    
                // Close window
                button.addEventListener('click', function(e) {
                    this.minPrice = prt.minPrice;
                    this.maxPrice = prt.maxPrice;
                    alert(this.minPrice);
                    alert(this.maxPrice);
    
                    if(this.minPrice != '' && this.maxPrice != '') {
                        range.text = this.minPrice + ' - ' + this.maxPrice;
                    }
                    else if(this.minPrice != '') {
                        range.text = this.minPrice + ' - Any';                
                    }
                    else if(this.maxPrice != '') {
                        range.text = 'Any - ' + this.maxPrice;
                    }
                    else {
                        range.text = 'Any';
                    }
                    window.close();
                });
    }
    

    Class 2

    function priceRangeTable()
    {
        this.minPrice = '';
        this.maxPrice = '';
    
        this.getMinPriceRow = function() {    
            // Create row    
            var row = Ti.UI.createTableViewRow({
                height: 'auto',
                backgroundColor: '#ffffff',
                selectionStyle: Titanium.UI.iPhone.TableViewCellSelectionStyle.NONE
            });
    
            // Create label
            var label = Ti.UI.createLabel({
                text: 'Min Price',
                top: 5,
                left: 5,
                height: 'auto',
                color: '#000000',
                textAlign: 'left',
                font: { fontSize: 15 }                
            });
    
            // Create input
            var input = Ti.UI.createTextField({
                color: '#000000',
                top: 0,
                right: 5,
                height: 35,
                width: 200,
                hintText: 'Any',
                clearButtonMode: 1, // Show clear button
                borderStyle: Titanium.UI.INPUT_BORDERSTYLE_NONE,
                keyboardType: Titanium.UI.KEYBOARD_NUMBER_PAD
            });
    
            // Set min price value
            input.addEventListener('blur', function(e) {
                this.minPrice = e.source.value;
            });
    
            row.add(label);
            row.add(input);
    
            return row;
        }
    
        this.getMaxPriceRow = function() {
            // Create row
            var row = Ti.UI.createTableViewRow({
                height: 'auto',
                backgroundColor: '#ffffff',
                selectionStyle: Titanium.UI.iPhone.TableViewCellSelectionStyle.NONE
            });
    
            // Create label
            var label = Ti.UI.createLabel({
                text: 'Max Price',
                top: 5,
                left: 5,
                height: 'auto',
                color: '#000000',
                textAlign: 'left',
                font: { fontSize: 15 }                
            });
    
            var input = Ti.UI.createTextField({
                color: '#000000',
                top: 0,
                right: 5,
                height: 35,
                width: 200,
                hintText: 'Any',
                clearButtonMode: 1, // Show clear button
                borderStyle: Titanium.UI.INPUT_BORDERSTYLE_NONE,
                keyboardType: Titanium.UI.KEYBOARD_NUMBER_PAD
            });
    
            // Set max price value
            input.addEventListener('blur', function(e) {
                this.maxPrice = e.source.value;
            });
    
            row.add(label);
            row.add(input);
            return row;
        }
    }
    

    Can anyone help? Its probably some simple coding error but I can't seem to work it out.

    — answered January 12th 2011 by Lyndon Hook
    permalink
    0 Comments
  • What you need to do is pass the context of your class into the object that listening for an event:

    this.myFunction = function() {
        // Some code here.
        someAnimation.parent = this;
        someAnimation.addEventListener('complete', function(e) {
            e.source.parent.myOtherFunction();
            // Ps. it might be: this.parent.myOtherFunction();
        });
    }
    
    — answered January 12th 2011 by Roger Chapman
    permalink
    1 Comment
    • Thanks for responding Roger - I ended up doing something very similar to what you suggested, although I've latterly discovered an alternative (better) method to do (I think) the same thing:

      this.myFunction= function() {
          return function(myThing) {
              // myThing (was 'this') available now...
          }(this);
      };
      

      Best wishes,

      Toby

      — commented January 12th 2011 by Toby Mathews
The ownership of individual contributions to this community generated content is retained by the authors of their contributions.
All trademarks remain the property of the respective owner.