July 23rd, 2013
London Titanium
Alloy Tips & Tricks
FOKKE ZANDBERGEN
app imagineer
Alloy Tips & Tricks
Compilation process
Not your mother's MVC
TSS
XML
Views
+
=
Definition
=
Models Controllers
Assets
config.json
Compilation process
Not your mother's MVC
Definition
=
Models Controllers
Assets
config.json
JS
Compilation process
Not your mother's MVC
Definition
=
Models Controllers
Assets
config.json
JSCommonJS
Compilation process
Not your mother's MVC
Collections
Sync
Store
Models Controllers
Assets
config.json
JSCommonJS
Compilation process
Not your mother's MVC
Collections
Sync
Store
Models Controllers
Assets
config.json
JSCommonJS
Compilation process
Not your mother's MVC
Collections
Sync
Store
Models Controllers
Assets
config.jsonAlloy.CFG
JSCommonJS
Compilation process
Not your mother's MVC
Collections
Sync
Store
Models Controllers
Assets
config.jsonAlloy.CFG
JSCommonJS
Compiled controllers
The first might be last
function Controller() {
!
// Controller functions
function myFoo() {
alert("Sa...
Compiled controllers
About $, exports and this
$.label === $.__views.label === this.label;
exports.label === undefined;
ex...
Titanium Studio Shortcuts
Be lazy
⇧⌘C New controller + view + style
⇧⌘Y New widget
⇧⌘M New model
⇧⌘I New migration
More: h...
Installing Alloy from Github
Living on the edge
sudo npm install -g git://github.com/appcelerator/alloy.git
Rollback to st...
Hacking Alloy
Have the last word
/app/assets/alloy.js
/app/assets/alloy/backbone.js
/app/assets/alloy/underscore.js
/app/a...
WPATH
Which Path | | Widget Path
function WPATH(s) {
var index = s.lastIndexOf("/");
var path = -1 === index
? "myWidget/"...
Custom sync adapters
.. for widget models
/app/widgets/my.widget/assets/alloy/sync/myAdapter.js
Drop your sync adapter in:...
All-in-one widget
Know the 'name'
Bundle a group of widgets as one
<Widget src="myMenus" /><!-- default: widget(.js) -->
<...
Styleable & Themable widgets
The . and # game
Set ID and class of view components to same, globally unique value
<Alloy>
!...
__parentSymbol
Who's your daddy?
<Alloy>
! <Window>
! ! <Widget src="randomBgColor" />
! </Window>
</Alloy>
__parentSymbol...
Stateful widgets
Keeping track
<Alloy>
! <Window class="container" layout="vertical">
! ! <Widget src="stateful" />
! ! <W...
Data Binding
3 flavours
<Model id="instance" src="myModel" instance="true" />
<Label id="a" text="{field}" />
<Label id="b"...
Bind an existing model
Workarounds
function openDetail(e) {
! var model = col.get(e.rowData.modelId);
! model.__transform ...
Main controller switching
Skipping index.js
var Alloy = require("alloy"), _ = Alloy._, Backbone = Alloy.Backbone;
Alloy.cr...
Reset your app.tss
Clean slate
'Label[platform=android]': { // Instead of platform-dependent
color: '#000' }
 
'Window': {...
@import TSS
Or the power of alloy.jmk
@import "reset.tss";
"Window": {
! backgroundColor: 'black'
}
Source: http://go.fokk...
Jade 2 XML
Be lazy like David Bankier
<Alloy>
<Window class="container">
<Label id="label" onClick="doClick">Hello, World<...
XML 2 TSS
Be lazy like David Bankier
<Alloy>
<Window class="container">
<Label id="label" onClick="doClick">Hello, World</...
Less TSS
Be lazy like David Bankier
@primColor: "blue";
.bg (@color) {
backgroundColor: $color
}
".container" : {
.bg($pri...
Detecting Alloy
Using Alloy libs without Alloy
var isAlloy = (typeof ENV_TEST === 'boolean');
• Alloy constants like OS_IO...
Wrapping Ti.UI.* components
.. using widgets or CommonJS modules
<ImageView image="http://my.im/age.png" />
Before
<Widget...
Wrapping Ti.UI.* components
Passing arguments
exports.setText = function (text) { $.myVew.text = text.toUpperCase(); }
_.e...
Wrapping Ti.UI.* components
Passing functions
_.each(['resume', 'pause', 'hide'], function (fn) {
if (!exports[fn]) {
! ex...
Wrapping Ti.UI.* components
Passing events
exports.on = $.myVew.addEventListener;
exports.off = $.myVew.removeEventListene...
Resources
Must reads
• Alloy docs
http://go.fokkezb.nl/alloydocs
• Backbone.js 0.9.2
http://go.fokkezb.nl/bb092
• Undersco...
Questions?
mail@FokkeZB.nl
www.FokkeZB.nl
@FokkeZB
Appcelerator Titanium Alloy tipstricks by Fokke Zandbergen
Appcelerator Titanium Alloy tipstricks by Fokke Zandbergen
Upcoming SlideShare
Loading in...5
×

Appcelerator Titanium Alloy tipstricks by Fokke Zandbergen

10,242

Published on

Appcelerator Titanium Alloy tipstricks by Fokke Zandbergen

This is not his official account I just re uploaded it here to make it easier for people to find and learn.
you can follow him : http://fokkezb.nl/

Published in: Technology, Business
0 Comments
16 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
10,242
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
128
Comments
0
Likes
16
Embeds 0
No embeds

No notes for slide

Transcript of "Appcelerator Titanium Alloy tipstricks by Fokke Zandbergen"

  1. 1. July 23rd, 2013 London Titanium Alloy Tips & Tricks FOKKE ZANDBERGEN app imagineer
  2. 2. Alloy Tips & Tricks
  3. 3. Compilation process Not your mother's MVC TSS XML Views + = Definition = Models Controllers Assets config.json
  4. 4. Compilation process Not your mother's MVC Definition = Models Controllers Assets config.json JS
  5. 5. Compilation process Not your mother's MVC Definition = Models Controllers Assets config.json JSCommonJS
  6. 6. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.json JSCommonJS
  7. 7. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.json JSCommonJS
  8. 8. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.jsonAlloy.CFG JSCommonJS
  9. 9. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.jsonAlloy.CFG JSCommonJS
  10. 10. Compiled controllers The first might be last function Controller() { ! // Controller functions function myFoo() { alert("Says bar"); } var $ = this; var exports = {}; ! // Parsed XML view $.__views.label = Ti.UI.createLabel({ id: "label" }); $.__views.label && $.addTopLevelView($.__views.label); _.extend($, $.__views); ! // Controler code $.myLabel.text = "Hello London!"; exports.myFoo = myFoo; _.extend($, exports); } var Alloy = require("alloy"), Backbone = Alloy.Backbone, _ = Alloy._; module.exports = Controller;
  11. 11. Compiled controllers About $, exports and this $.label === $.__views.label === this.label; exports.label === undefined; exports.foo = 'bar'; $.bar = 'foo'; Inline code function myFunction() { ! $.label === $.__views.label; ! this.label === exports.label === undefined; ! ! $.foo === exports.foo; ! this.foo = undefined; exports.bar === undefined; } Functions
  12. 12. Titanium Studio Shortcuts Be lazy ⇧⌘C New controller + view + style ⇧⌘Y New widget ⇧⌘M New model ⇧⌘I New migration More: http://go.fokkezb.nl/ttshortcuts
  13. 13. Installing Alloy from Github Living on the edge sudo npm install -g git://github.com/appcelerator/alloy.git Rollback to stable sudo npm uninstall -g alloy sudo npm install -g alloy *Drop "sudo" on Windows
  14. 14. Hacking Alloy Have the last word /app/assets/alloy.js /app/assets/alloy/backbone.js /app/assets/alloy/underscore.js /app/assets/alloy/sync/sql.js /app/themes/myTheme/assets/alloy/CFG.js • The SQLite sync adapter is not compatible with Backbone.js 1.x • Make sure you sync config.json changes to your CFG.js files Alloy.isTablet = function() { return (Ti.Platform.displayCaps.platformWidth > 800); } app/alloy.js .. or go wild and overwrite Extend via app.js
  15. 15. WPATH Which Path | | Widget Path function WPATH(s) { var index = s.lastIndexOf("/"); var path = -1 === index ? "myWidget/" + s : s.substring(0, index) + "/myWidget/" + s.substring(index + 1); return path; } app/widgets/myWidget/assets/foo.png Resources/myWidget/foo.png app/widgets/myWidget/assets/one/two/three.png Resources/one/two/MyWidget/three.png Examples • Assets and libs the same • Place stuff in platform specific iphone, android folders • Place stuff in the images folder
  16. 16. Custom sync adapters .. for widget models /app/widgets/my.widget/assets/alloy/sync/myAdapter.js Drop your sync adapter in: exports.definition = { config: { adapter: { type: 'my.widget/myAdapter' } } }; Use in widget models: /Resources/alloy/sync/my.widget/myAdapter.js It will end up in: /app/widgets/my.widget/models/myModel.js
  17. 17. All-in-one widget Know the 'name' Bundle a group of widgets as one <Widget src="myMenus" /><!-- default: widget(.js) --> <Widget src="myMenus" name="slide" /> <Widget src="myMenus" name="drawer" /> *Available since Alloy 1.1 Specific controller per context <Widget src="myList" /><!-- default: widget(.js) --> <Widget src="myList" name="tab" /> <Widget src="myList" name="window" /> <Widget src="myList" name="view" /> Alloy.createWidget("nl.fokkezb.tweetsView", "widget", {      id: "myWidget",      foo: "bar" });
  18. 18. Styleable & Themable widgets The . and # game Set ID and class of view components to same, globally unique value <Alloy> ! <Label id="myWidgetLabel" class="myWidgetLabel" /> </Alloy> Apply defaults styles using classes ".myWidgetLabel": { ! color: 'red' } "#myWidgetLabel": { ! color: 'blue' } Instruct developers using your widget to override using IDs More: http://go.fokkezb.nl/alloytssprio (widgets missing)
  19. 19. __parentSymbol Who's your daddy? <Alloy> ! <Window> ! ! <Widget src="randomBgColor" /> ! </Window> </Alloy> __parentSymbol.backgroundColor = '#'+Math.floor(Math.random()*16777215).toString(16); app/widgets/randomBgColor/controllers/widget.js
  20. 20. Stateful widgets Keeping track <Alloy> ! <Window class="container" layout="vertical"> ! ! <Widget src="stateful" /> ! ! <Widget src="stateful" /> ! </Window> </Alloy> var state = require(WPATH('state')); $.instanceCounter.text = state.counter++; exports.counter = 0; app/widgets/stateful/assets/state.js app/widgets/stateful/controllers/widget.js app/views/index.xml
  21. 21. Data Binding 3 flavours <Model id="instance" src="myModel" instance="true" /> <Label id="a" text="{field}" /> <Label id="b" text="{singleton.field}" /> <Label id="c" text="{$.instance.field}" /> var $model = arguments[0] ? arguments[0]["$model"] : null; $.instance = Alloy.createModel("myModel"); $.__views.a.text = "undefined" != typeof $model.__transform["field"] ? $model.__transform["field"] : $model.get("field"); var __alloyId1 = function() { $.b.text = _.isFunction(Alloy.Models.singleton.transform) ? Alloy.Models.singleton.transform()["field"] : Alloy.Models.singleton.get("field"); }; Alloy.Models.singleton.on("fetch change destroy", __alloyId1); var __alloyId2 = function() { $.c.text = _.isFunction($.instance.transform) ? $.instance.transform()["field"] : $.instance.get("field"); }; $.instance.on("fetch change destroy", __alloyId2);
  22. 22. Bind an existing model Workarounds function openDetail(e) { ! var model = col.get(e.rowData.modelId); ! model.__transform = myTransformer(model); // model.toJSON(); ! Alloy.createController('detail', { ! ! '$model': model ! }); } function openDetail(e) { ! var detailModel = col.get(e.rowData.modelId); ! detailModel.__transform = myTransformer(detailModel); ! detailModel.transform = function() { return this.__transform; }; ! Alloy.Models.detailModel = detailModel; ! Alloy.createController('detail'); } Pre-setting a singleton Emulating a dataCollection loop WARNING: No change listeners
  23. 23. Main controller switching Skipping index.js var Alloy = require("alloy"), _ = Alloy._, Backbone = Alloy.Backbone; Alloy.createController("index"); • Alloy always requires index.xml app.js // $.index.open(); if (Ti.App.Properties.getBool('isLoggedIn', false)) { Alloy.createController("home"); } else { Alloy.createController("login"); } index.js <Alloy /> index.xml
  24. 24. Reset your app.tss Clean slate 'Label[platform=android]': { // Instead of platform-dependent color: '#000' }   'Window': { // More common-sense default vs 'transparent' backgroundColor: '#fff' }   'Window[platform=android]': { // Never lightweight (deprecated) modal: false }   'TextField': { // More common-sense default vs un-styled borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED }   'ImageView[platform=ios]': { // Never show ugly temporary image preventDefaultImage: true } } Discussion: http://go.fokkezb.nl/alloyreset
  25. 25. @import TSS Or the power of alloy.jmk @import "reset.tss"; "Window": { ! backgroundColor: 'black' } Source: http://go.fokkezb.nl/alloyimport task("pre:compile", function(event, logger) { ! explodeImport(event, logger); }); task("post:compile", function(event, logger) { ! implodeImport(event, logger); }); app/alloy.jmk
  26. 26. Jade 2 XML Be lazy like David Bankier <Alloy> <Window class="container"> <Label id="label" onClick="doClick">Hello, World</Label> </Window> </Alloy> Blog: http://go.fokkezb.nl/alloyjade Alloy Window.container Label#label(onClick="doClick") Hello, World app/views/index.jade • No need for closing tags • Advanced templating • Advanced conditions
  27. 27. XML 2 TSS Be lazy like David Bankier <Alloy> <Window class="container"> <Label id="label" onClick="doClick">Hello, World</Label> </Window> </Alloy> Source: https://github.com/dbankier/xml2tss ".container": {} ".#label": {} xml2tss index.xml ../styles/index.tss • Will update existing TSS • Integrated in Alloy 1.2
  28. 28. Less TSS Be lazy like David Bankier @primColor: "blue"; .bg (@color) { backgroundColor: $color } ".container" : { .bg($primColor); } Source: https://github.com/dbankier/ltss ".container" : { backgroundColor: "blue" } ltss index.ltss index.tss
  29. 29. Detecting Alloy Using Alloy libs without Alloy var isAlloy = (typeof ENV_TEST === 'boolean'); • Alloy constants like OS_IOS don't exist at run-time • They are replaced by TRUE|FALSE during compile • Code blocks that will never execute are removed • In Vanilla Titanium they will be undefined var Alloy = require('alloy'); Alloy.infect && Alloy.infect(this); myLib.js or app.js (3.1+) Source: http://go.fokkezb.nl/alloydetect
  30. 30. Wrapping Ti.UI.* components .. using widgets or CommonJS modules <ImageView image="http://my.im/age.png" /> Before <Widget src="ImageView" image="http://my.im/age.png" /> After: <ImageView module="My.UI" image="http://my.im/age.png" /> Coming in Alloy 1.2: • Pass on or intercept common parameters, functions and events /app/widgets/ImageView/controllers/widget.js require('My.UI').createImageView() <ImageView ns="require('My.UI')" image="http://my.im/age.png" /> Simple, durable workaround:
  31. 31. Wrapping Ti.UI.* components Passing arguments exports.setText = function (text) { $.myVew.text = text.toUpperCase(); } _.each(['text', 'color'], function (pr) { var cam = pr[0].toUpperCase() + pr.substring(1); var get = exports['get' + cam] || ($['get' + cam] = function () { retur $.myVew[pr]; }); var set = exports['set' + cam] || ($['set' + cam] = function (val) { $.myVew[pr] = val; }); Object.defineProperty($, pr, { get: get, set: set }); }); exports.applyProperties = function(properties) { properties = _.omit(properties, 'id', '__parentSymbol', '__itemTemplate', '$model'); var apply = {}; _.each(properties, function (val, pr) { ! var fn = 'set' + pr[0].toUpperCase() + pr.substring(1); ! exports[fn] ? exports[fn](val) : (apply[pr] = val); }); _.isEmpty(apply) || $.myVew.applyProperties(apply); } exports.applyProperties(arguments[0]); • Looping _.keys($.myVew) would only give set properties • Add set/get on $ as so applyProperties can't find them • Define properties on $ as that's the final object • Filter Alloy properties as (__parentSymbol would give memory leak)
  32. 32. Wrapping Ti.UI.* components Passing functions _.each(['resume', 'pause', 'hide'], function (fn) { if (!exports[fn]) { ! exports[fn] = $.myVew[fn]; } }); • Remember we already did setters and getters for properties
  33. 33. Wrapping Ti.UI.* components Passing events exports.on = $.myVew.addEventListener; exports.off = $.myVew.removeEventListener; exports.trigger = $.myVew.fireEvent; • For (widget) controllers onClick translates to .on('click') <Widget src="ImageView" image="http://my.im/age.png" onClick="doClick" />
  34. 34. Resources Must reads • Alloy docs http://go.fokkezb.nl/alloydocs • Backbone.js 0.9.2 http://go.fokkezb.nl/bb092 • Underscore.js http://go.fokkezb.nl/undscore • Moment.js http://go.fokkezb.nl/momentjs • Alloy Google Group http://go.fokkezb.nl/alloygroup • Alloy Q&A http://go.fokkezb.nl/alloyqa • Alloy changelog http://go.fokkezb.nl/alloylog • Alloy test apps http://go.fokkezb.nl/alloytests • Alloy compiler source http://go.fokkezb.nl/alloycompiler • Alloy widgets @ AlloyLove.com • Twitter: #TiAlloy http://go.fokkezb.nl/alloylinks
  35. 35. Questions? mail@FokkeZB.nl www.FokkeZB.nl @FokkeZB
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×