main issue
Currently classes assigned to Titanium proxy objects created with XML elements and/or *Alloy.UI.create()* do not store the classes on the proxy object itself. They are used only to generate the style and then are forgotten. To this point this is because any additional assignments to a proxy object can be considered unnecessary overhead. In an effort to make dynamic styling (ALOY-210), and specifically class manipulation (ALOY-613) more intuitive, we should store the classes in an efficient manner so they can be used on subsequent style operations.
To do this, we should add a *classes* and *apiName* property to Ti proxies when they are created via markup or *Alloy.UI.create()*. If there are proxies created by other means, classes can be added as an array or string to be used by further style operations. Here's a few examples:
var proxy;
proxy = $.UI.create('Ti.UI.Button', {
classes: ['dark','blue']
});
Ti.API.info(proxy.classes);
Ti.API.info(proxy.apiName);
// OUTPUT: ['dark','blue']
// OUTPUT: 'Ti.UI.Button'
proxy = $.UI.create('Ti.UI.Label', {
classes: 'dark blue'
});
Ti.API.info(proxy.classes);
Ti.API.info(proxy.apiName);
// OUTPUT: ['dark','blue']
// OUTPUT: 'Ti.UI.Label'
<ImageView id="yoyo" class="images somethingElse"/>
Ti.API.info($.yoyo.classes);
Ti.API.info($.yoyo.apiName);
// OUTPUT: ['images','somethingElse']
// OUTPUT: 'Ti.UI.ImageView'
additional considerations
We need to make sure that this does not cause any excessive overhead on the creation of Titanium proxies with Alloy. A little overhead is acceptable and expected when actually manipulating styles at runtime, but the initial creation of the proxy should remain largely unaffected. We will need to verify proxy creation performance as part of this ticket.
We also need to make sure that all platforms are aware of *classes* and *apiName* being used for this purpose on proxies. We also need to make sure documentation is created in the API docs to show this property.
crude performance tester
index.xml
<Alloy>
<Window>
<Button onClick="test">test</Button>
</Window>
</Alloy>
index.js
$.index.open();
function test() {
var total = 0;
var start, thisOne;
for (var j = 0; j < 10; j++) {
start = new Date().getTime();
for (var i = 0; i < 10000; i++) { // only used 100 on android
Alloy.createController('test');
}
thisOne = (new Date().getTime()) - start;
total += thisOne;
Ti.API.info('test #' + (j+1) + ': ' + thisOne);
}
Ti.API.info('average: ' + (total/10));
}
test.xml
<Alloy>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
<View class="bob lou"/>
</Alloy>
PR: https://github.com/appcelerator/alloy/pull/157 test app: https://github.com/appcelerator/alloy/tree/master/test/apps/testing/ALOY-706 Functional test can pass if the app is run on all supported platforms and all runtime unit tests pass.
Functional and unit tests passed on iOS, Android and MobileWeb platforms. Titanium SDK 3.1.2.v20130726192706 Alloy 1.2.0-alpha Appcelerator Studio 3.1.3.201307252418 CLI 3.1.2 Node 0.8.22 Closing.
PR: https://github.com/appcelerator/alloy/pull/322 test should pass all runtime tests now