How can i access a variable in an event on android?

You must Login before you can answer or comment on any questions.

Hi, what I want to do works fine with iPhone, but not with Android. I have to say that I'm not an JavaScript expert, may be I do some basic thing wrong. This is my code snippet of file DatasetListController.js:

function DatasetListController(aDatasetType, aMainTab) {
 
    var DatasetListView = require('ui/DatasetListView');
    this.datasetListView = new DatasetListView(aDatasetType);
    this.listWindow = this.datasetListView.listWindow;
 
    Ti.API.info('listWindow '+ this.listWindow.tile);
 
    // hide searchbar, because the searchbar has the focus and shows the keyboard on Android
    if (Ti.Platform.osname == 'android') {
        this.listWindow.addEventListener('open', function(e) {
            setTimeout(function(e) {
                // ERROR
                datasetListView.searchBar.blur();
                // this.datasetListView doesn't work too
            }, 250);
        });
    };
    ....
}
This is a snippet of DatasetListView.js
function DatasetListView(aDatasetType) {
 
    // create window for datasetlist
    this.listWindow = Ti.UI.createWindow({
        title: aDatasetType,
        backgroundColor: '#fff',
        tabBarHidden: true
    });
 
    this.searchBar = Titanium.UI.createSearchBar({
        barColor:'#000', 
        showCancel:true,
        height:43,
        top:0,
    });
 
    // create main tableview
    this.listView = Ti.UI.createTableView({
        //style: Ti.UI.iPhone.TableViewStyle.GROUPED,
        scrollable: true,
        search: this.searchBar
    });
    this.listWindow.add(this.listView);
 
    return this;
};
module.exports = DatasetListView;
I always get an error when accessing datasetListView in my 'open'-event of my listWindow. On iPhone it works fine. I only have problems with Android.

3 Answers

Accepted Answer

You've encountered a glitch in the iOS implementation of CommonJS. On iOS, you can access the global namespace from within a CommonJS module.

CommonJS modules should not have access to globals; the Android behavior is correct. Your best bet is to avoid global variables entirely. You can always define a CommonJS module that can maintain a map of global variables in a static variable. Anybody who needs to access those values can just require your module to get to them.

— answered 7 months ago by Jason Priebe
answer permalink
3 Comments
  • When i always use this.... in my module, I don't have a global variable, do I? In which coderow do you see the problem?

    — commented 7 months ago by Alexander Stark

  • You're right -- I was too hasty in diagnosing the problem (although the problem I describe does impact a lot of users).

    At any rate, what if you tried this:

    function DatasetListController(aDatasetType, aMainTab) {
     
        var DatasetListView = require('ui/DatasetListView');
        var datasetListView = new DatasetListView(aDatasetType);
        this.datasetListView = datasetListView;
        this.listWindow = this.datasetListView.listWindow;
     
        Ti.API.info('listWindow '+ this.listWindow.tile);
     
        // hide searchbar, because the searchbar has the focus and shows the keyboard on Android
        if (Ti.Platform.osname == 'android') {
            this.listWindow.addEventListener('open', function(e) {
                setTimeout(function(e) {
                    datasetListView.searchBar.blur();
                }, 250);
            });
        };
        ....
    }
    The problem with the first form you had is that you do not have any variable called datasetListView. Then you tried to use this.datasetListView, but when your event listener is called, this does not refer to your DatasetListController object; it refers to this.listWindow (the target of the event).

    Here's a simpler example:

    function TestWindow ()
    {
        this.window = Ti.UI.createWindow ({backgroundColor: '#f00'});
     
        this.button = Ti.UI.createButton ({top: 50, left: 10, right: 10, title: 'Click Me'});
     
        this.window.add (this.button);
     
        this.button.addEventListener ('click', function (e) {
           // will not work -- "this" refers to the button that was clicked
           this.button.hide (); 
        });
    }
     
    module.exports = TestWindow;
    that didn't work, but this does:
    function TestWindow ()
    {
        var _self = {};
        _self.window = Ti.UI.createWindow ({backgroundColor: '#f00'});
     
        _self.button = Ti.UI.createButton ({top: 50, left: 10, right: 10, title: 'Click Me'});
     
        _self.window.add (_self.button);
     
        _self.button.addEventListener ('click', function (e) {
            // this works because "_self" doesn't change; it is scoped to the
            // the TestWindow2() function
            _self.button.hide (); 
        });
     
        return _self;
    }
     
    module.exports = TestWindow;
    Then you could ask yourself why you're attaching all these controls to the object so that they're accessible outside the object. Presumably, only TestWindow needs to deal with the button. So keep it private:
    function TestWindow ()
    {
        var _self = {};
        _self.window = Ti.UI.createWindow ({backgroundColor: '#f00'});
     
        var _button = Ti.UI.createButton ({top: 50, left: 10, right: 10, title: 'Click Me'});
     
        _self.window.add (_button);
     
        _button.addEventListener ('click', function (e) {
            _button.hide (); 
        });
     
        return _self;
    }
     
    module.exports = TestWindow;
    Finally, if you're like me, you'd prefer that your TestWindow behaves like a true Titanium Window object, so you use parasitic inheritance (there are caveats to this, so be sure you understand those before you adopt this strategy).
    function TestWindow ()
    {
        var _self = Ti.UI.createWindow ({backgroundColor: '#f00'});
     
        var _button = Ti.UI.createButton ({top: 50, left: 10, right: 10, title: 'Click Me'});
     
        _self.add (_button);
     
        _button.addEventListener ('click', function (e) {
            _button.hide (); 
        });
     
        return _self;
    }
     
    module.exports = TestWindow;
    Now you can use the class like this:
    var TestWindow = require ('/TestWindow');
    var win = new TestWindow ();
    win.open ();

    — commented 7 months ago by Jason Priebe

  • Thanks, this would help me

    — commented 7 months ago by Alexander Stark

It's also not possible to access variables from an internal function in the same js-File:

function DatasetListController(aDatasetType, aMainTab) {
 
        var DatasetListView = require('ui/DatasetListView');
        this.datasetListView = new DatasetListView(aDatasetType);
    ...
        getData(); // call internal function
    return this;
};
 
// INTERNAL FUNCTIONS
function getData() {
    // ERROR datasetListView is undefined
    Ti.API.info('listWindow2 '+ datasetListView.listWindow.title);
    // this.datasetListView doesn't work, too
};
What I'm doing wrong?

hi,

you can try this code

function DatasetListController(aDatasetType, aMainTab) {
 
    var DatasetListView = require('ui/DatasetListView');
    this.listWindow = new DatasetListView(aDatasetType);
 
    this.datasetListView = this.listWindow.listView;
 
    Ti.API.info('listWindow '+ this.listWindow.tile);
 
    // hide searchbar, because the searchbar has the focus and shows the keyboard on Android
    if (Ti.Platform.osname == 'android') {
        this.listWindow.addEventListener('open', function(e) {
            setTimeout(function(e) {
                // ERROR
                datasetListView.searchBar.blur();
                // this.datasetListView doesn't work too
            }, 250);
        });
    };
    ....
}
 
function DatasetListView(aDatasetType) {
 
    // create window for datasetlist
    var listWindow = Ti.UI.createWindow({
        title: aDatasetType,
        backgroundColor: '#fff',
        tabBarHidden: true
    });
 
    var searchBar = Titanium.UI.createSearchBar({
        barColor:'#000', 
        showCancel:true,
        height:43,
        top:0,
    });
 
    // create main tableview
    var listView = Ti.UI.createTableView({
        //style: Ti.UI.iPhone.TableViewStyle.GROUPED,
        scrollable: true,
        search: searchBar
    });
 
    listWindow.listView = listView;
 
    listWindow.add(listView);
 
    return listWindow;
};
 
module.exports = DatasetListView;

— answered 7 months ago by Mitul Bhalia
answer permalink
2 Comments
  • I'll test this, but i don't want to return the window object. I want to return this!

    — commented 7 months ago by Alexander Stark

  • ok then try to declare this variable as dictionary

    function DatasetListView(aDatasetType) {
        var this = {
        };
        // create window for datasetlist
        this.listWindow = Ti.UI.createWindow({
            title: aDatasetType,
            backgroundColor: '#fff',
            tabBarHidden: true
        });
     
        this.searchBar = Titanium.UI.createSearchBar({
            barColor:'#000', 
            showCancel:true,
            height:43,
            top:0,
        });
     
        // create main tableview
        this.listView = Ti.UI.createTableView({
            //style: Ti.UI.iPhone.TableViewStyle.GROUPED,
            scrollable: true,
            search: this.searchBar
        });
        this.listWindow.add(this.listView);
     
        return this;
    };
    module.exports = DatasetListView;

    — commented 7 months ago by Mitul Bhalia

Your Answer

Think you can help? Login to answer this question!