Titanium Community Questions & Answer Archive

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

Reusing util code in windows created from TableViews

I have some utility code in a file, say utils.js. These are things like like adding an each() method to arrays and what have you. I want to use these in a variety of (sub)contexts.

What's the best way to do this?

(the rest of this question details what I did, but I'm not convinced I'm doing things the best way so feel free to chime in with an answer)

Currently, I am including via Titanium.include() in each implementation file of the Window (i.e. the file pointed to by the url parameter to the constructor). For example, assuming the Window implementation for the TableView is in a file called TableView.js and the window implementation for the Window of the table row is in a file called Detail.js:

TableView.js

Titanium.include( 'utils.js' );

tableRowDetail = Titanium.UI.createWindow({
  url   : 'Detail.js',
  title : "This is the detail",
});

Detail.js

Titanium.include( 'utils.js' );

...

// access the helper
$A(someArray).each(function() { ... });

This works, but I wonder about the performance here. For example, given a TableView with 50 rows - every time the user selects a row to see more detail a new Window is created thus requiring utils.js to be read in again. This seems horribly inefficient.

Another way I thought of was to provide subcontexts with the util reference from their parent contexts. For example, assuming my util code was housed in a Util object, something like:

TableView.js

Titanium.include( 'utils.js' );

tableRowDetail = Titanium.UI.createWindow({
  url   : 'Detail.js',
  title : "This is the detail",
});

tableRowDetail.Util = Util;

Detail.js

Util = Titanium.UI.currentWindow.Util;

...

// access the helper
Util.$A(someArray).each(function() { ... });

This would work, but it would only work if my utils.js file houses everything in a Util object. This wouldn't work if utils.js had free-standing global functions.

Inverting the problem as a solution here, we could capture global functions by using a special Window to house the utility code and pass around a reference to this context. I looked into this for a bit but no dice. I was thinking the subcontext could callback onto the parent context at which time the subcontext could pass itself to the parent context through the callback. The context could be stored in a variable in the parent context. I was hoping to use events to wait on in order to ensure that the Util reference is available to the rest of the app, however, I can't seem to get a subcontext to fire event that is observable by its parent context…

— asked May 5th 2010 by Donnie Tognazzini
  • code
  • context
  • globals
  • modularization
  • organization
  • reuse
  • sharing
  • subcontext
0 Comments

1 Answer

  • Donnie,

    Found your question while looking into accepted practices in Titanium apps. Haven't really seen much that directly addresses the problem but I do have something that works pretty well.

    First, I created a utils.js file containing a the "Utils" constructor:

    function Util() {
        //*** 'me' acts as an alias that can be used within the methods
        var me = this;
        //*** Public properties:
        this.someValue;
        this.someOtherValue;
    
        //*** Protected variables:
        var hushHush = "shhh";
    
    
        //*** Public methods:
        Util.prototype.foo = function (arg1, arg2) {
            //*** Note use of 'me' to access property
            return (arg1 + arg2) * me.somevalue;
        };
    
        Util.prototype.bar = function (arg1, arg2) {
            //*** You can also use 'me' to reference methods within other methods
            var baz = me.foo(arg1, arg2);
            return parseInt(baz,10);
        };
    
        //*** Protected method used only internally. Call with 'me.my_own()'
        this.my_own = function (arg1) {
        };
    }
    

    Next, I create an instance of Util in app.js and assign it to a Ti.App variable so that it becomes available throughout the app:

    Ti.include("./js/util.js");
    
    Ti.App.Util = new Util();
    

    Finally, within any other window, I can use the Util object like this:

    var myValue = Ti.App.Util.foo(20,30);
    

    Regards,

    Mark

    — answered December 10th 2010 by Mark Pemburn
    permalink
    3 Comments
    • Just about to try this out and if it works for me then this is great.

      What Appcelerator needs is a "Best Practices" guide as there's good info out there but its trolling through the q&a to find it…..

      You should also be able to subscribe to the q&a discussion as a whole :-)

      — commented January 13th 2011 by Chris Moore
    • This works perfectly!

      Thanks for sharing this technique. It should definitely appear somewhere in the "Best Practices" guide!

      — commented April 2nd 2011 by Dennis Lo
    • thanks for sharing , I was struggling … with accessing all the vars … globally …

      — commented May 9th 2011 by Iain Campion
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.