SlideShare a Scribd company logo
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("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;
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
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
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
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
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
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
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"
});
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)
__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
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
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);
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
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
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
@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
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
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
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
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
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:
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)
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
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" />
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
Questions?
mail@FokkeZB.nl
www.FokkeZB.nl
@FokkeZB

More Related Content

What's hot

Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
Visual Engineering
 
jQuery in 15 minutes
jQuery in 15 minutesjQuery in 15 minutes
jQuery in 15 minutes
Simon Willison
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
Remy Sharp
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
Sergey Bolshchikov
 
RubyMotion
RubyMotionRubyMotion
RubyMotion
Mark
 
jQuery PPT
jQuery PPTjQuery PPT
jQuery PPT
Dominic Arrojado
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
Visual Engineering
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
manugoel2003
 
Workshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSWorkshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJS
Visual Engineering
 
Creating GUI Component APIs in Angular and Web Components
Creating GUI Component APIs in Angular and Web ComponentsCreating GUI Component APIs in Angular and Web Components
Creating GUI Component APIs in Angular and Web Components
Rachael L Moore
 
Boost your angular app with web workers
Boost your angular app with web workersBoost your angular app with web workers
Boost your angular app with web workers
Enrique Oriol Bermúdez
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
Keith Bloomfield
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012
Nicholas Zakas
 
Single Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and RailsSingle Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and Rails
Prateek Dayal
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmineRubyc Slides
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
Gunjan Kumar
 
Prototype & jQuery
Prototype & jQueryPrototype & jQuery
Prototype & jQuery
Remy Sharp
 
Creating GUI container components in Angular and Web Components
Creating GUI container components in Angular and Web ComponentsCreating GUI container components in Angular and Web Components
Creating GUI container components in Angular and Web Components
Rachael L Moore
 

What's hot (20)

Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
 
jQuery in 15 minutes
jQuery in 15 minutesjQuery in 15 minutes
jQuery in 15 minutes
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
 
RubyMotion
RubyMotionRubyMotion
RubyMotion
 
jQuery PPT
jQuery PPTjQuery PPT
jQuery PPT
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
 
Jquery
JqueryJquery
Jquery
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
 
Workshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSWorkshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJS
 
Creating GUI Component APIs in Angular and Web Components
Creating GUI Component APIs in Angular and Web ComponentsCreating GUI Component APIs in Angular and Web Components
Creating GUI Component APIs in Angular and Web Components
 
Boost your angular app with web workers
Boost your angular app with web workersBoost your angular app with web workers
Boost your angular app with web workers
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012
 
Single Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and RailsSingle Page Web Apps with Backbone.js and Rails
Single Page Web Apps with Backbone.js and Rails
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
 
Es.next
Es.nextEs.next
Es.next
 
Prototype & jQuery
Prototype & jQueryPrototype & jQuery
Prototype & jQuery
 
Creating GUI container components in Angular and Web Components
Creating GUI container components in Angular and Web ComponentsCreating GUI container components in Angular and Web Components
Creating GUI container components in Angular and Web Components
 

Similar to Alloy Tips & Tricks #TiLon

Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
Daniel Cukier
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
pootsbook
 
Basics of AngularJS
Basics of AngularJSBasics of AngularJS
Basics of AngularJS
Filip Janevski
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
Bert Wijnants
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js Fundamentals
Mark
 
Android L01 - Warm Up
Android L01 - Warm UpAndroid L01 - Warm Up
Android L01 - Warm Up
Mohammad Shaker
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Documenting from the Trenches
Documenting from the TrenchesDocumenting from the Trenches
Documenting from the TrenchesXavier Noria
 
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
Matt Raible
 
Styling components with JavaScript
Styling components with JavaScriptStyling components with JavaScript
Styling components with JavaScript
bensmithett
 
Angular 2 Essential Training
Angular 2 Essential Training Angular 2 Essential Training
Angular 2 Essential Training
Patrick Schroeder
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019
Matt Raible
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
David Rodenas
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Matt Raible
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
Alive Kuo
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
toddbr
 

Similar to Alloy Tips & Tricks #TiLon (20)

Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
Scala active record
Scala active recordScala active record
Scala active record
 
Basics of AngularJS
Basics of AngularJSBasics of AngularJS
Basics of AngularJS
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js Fundamentals
 
Android L01 - Warm Up
Android L01 - Warm UpAndroid L01 - Warm Up
Android L01 - Warm Up
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Documenting from the Trenches
Documenting from the TrenchesDocumenting from the Trenches
Documenting from the Trenches
 
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
 
Styling components with JavaScript
Styling components with JavaScriptStyling components with JavaScript
Styling components with JavaScript
 
Angular 2 Essential Training
Angular 2 Essential Training Angular 2 Essential Training
Angular 2 Essential Training
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019A Gentle Introduction to Angular Schematics - Angular SF 2019
A Gentle Introduction to Angular Schematics - Angular SF 2019
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
 
[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC[Coscup 2012] JavascriptMVC
[Coscup 2012] JavascriptMVC
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 

More from Fokke Zandbergen

Building the (Support) Robot at Zapier
Building the (Support) Robot at ZapierBuilding the (Support) Robot at Zapier
Building the (Support) Robot at Zapier
Fokke Zandbergen
 
Lessons from helping developers integrate 1,000 APIs with Zapier
Lessons from helping developers integrate 1,000 APIs with ZapierLessons from helping developers integrate 1,000 APIs with Zapier
Lessons from helping developers integrate 1,000 APIs with Zapier
Fokke Zandbergen
 
We are all Remote Advocates
We are all Remote AdvocatesWe are all Remote Advocates
We are all Remote Advocates
Fokke Zandbergen
 
Cross-platform Native App ontwikkeling met Appcelerator
Cross-platform Native App ontwikkeling met AppceleratorCross-platform Native App ontwikkeling met Appcelerator
Cross-platform Native App ontwikkeling met Appcelerator
Fokke Zandbergen
 
Building Native Mobile Apps using Javascript with Titanium
Building Native Mobile Apps using Javascript with TitaniumBuilding Native Mobile Apps using Javascript with Titanium
Building Native Mobile Apps using Javascript with Titanium
Fokke Zandbergen
 
Getting Started with Titanium & Alloy
Getting Started with Titanium & AlloyGetting Started with Titanium & Alloy
Getting Started with Titanium & Alloy
Fokke Zandbergen
 
Cross-Platform Native Apps with JavaScript
Cross-Platform Native Apps with JavaScriptCross-Platform Native Apps with JavaScript
Cross-Platform Native Apps with JavaScript
Fokke Zandbergen
 
Titanium: Develop Native Mobile Apps with JavaScript
Titanium: Develop Native Mobile Apps with JavaScriptTitanium: Develop Native Mobile Apps with JavaScript
Titanium: Develop Native Mobile Apps with JavaScript
Fokke Zandbergen
 
Appcelerator OSS & Platform
Appcelerator OSS & PlatformAppcelerator OSS & Platform
Appcelerator OSS & Platform
Fokke Zandbergen
 
Platform 4.0 Meetup Launch Event
Platform 4.0 Meetup Launch EventPlatform 4.0 Meetup Launch Event
Platform 4.0 Meetup Launch Event
Fokke Zandbergen
 
Appcelerator Alloy MVC
Appcelerator Alloy MVCAppcelerator Alloy MVC
Appcelerator Alloy MVC
Fokke Zandbergen
 
The Ultimate Titanium CLI Toolchain
The Ultimate Titanium CLI ToolchainThe Ultimate Titanium CLI Toolchain
The Ultimate Titanium CLI Toolchain
Fokke Zandbergen
 
Getting ready for iOS 8 & iPhone 6
Getting ready for iOS 8 & iPhone 6Getting ready for iOS 8 & iPhone 6
Getting ready for iOS 8 & iPhone 6
Fokke Zandbergen
 
Titanium Community Toolkit Showcase
Titanium Community Toolkit ShowcaseTitanium Community Toolkit Showcase
Titanium Community Toolkit Showcase
Fokke Zandbergen
 
Titanium Alloy Tutorial
Titanium Alloy TutorialTitanium Alloy Tutorial
Titanium Alloy Tutorial
Fokke Zandbergen
 
5 app alternatieven #AIB2013
5 app alternatieven #AIB20135 app alternatieven #AIB2013
5 app alternatieven #AIB2013
Fokke Zandbergen
 
Apps voor kerken #Kerk2013
Apps voor kerken #Kerk2013Apps voor kerken #Kerk2013
Apps voor kerken #Kerk2013
Fokke Zandbergen
 
TiNy #TiAppCamp
TiNy #TiAppCampTiNy #TiAppCamp
TiNy #TiAppCamp
Fokke Zandbergen
 
Internetmarketing
InternetmarketingInternetmarketing
Internetmarketing
Fokke Zandbergen
 
Alloy #DMC13
Alloy #DMC13Alloy #DMC13
Alloy #DMC13
Fokke Zandbergen
 

More from Fokke Zandbergen (20)

Building the (Support) Robot at Zapier
Building the (Support) Robot at ZapierBuilding the (Support) Robot at Zapier
Building the (Support) Robot at Zapier
 
Lessons from helping developers integrate 1,000 APIs with Zapier
Lessons from helping developers integrate 1,000 APIs with ZapierLessons from helping developers integrate 1,000 APIs with Zapier
Lessons from helping developers integrate 1,000 APIs with Zapier
 
We are all Remote Advocates
We are all Remote AdvocatesWe are all Remote Advocates
We are all Remote Advocates
 
Cross-platform Native App ontwikkeling met Appcelerator
Cross-platform Native App ontwikkeling met AppceleratorCross-platform Native App ontwikkeling met Appcelerator
Cross-platform Native App ontwikkeling met Appcelerator
 
Building Native Mobile Apps using Javascript with Titanium
Building Native Mobile Apps using Javascript with TitaniumBuilding Native Mobile Apps using Javascript with Titanium
Building Native Mobile Apps using Javascript with Titanium
 
Getting Started with Titanium & Alloy
Getting Started with Titanium & AlloyGetting Started with Titanium & Alloy
Getting Started with Titanium & Alloy
 
Cross-Platform Native Apps with JavaScript
Cross-Platform Native Apps with JavaScriptCross-Platform Native Apps with JavaScript
Cross-Platform Native Apps with JavaScript
 
Titanium: Develop Native Mobile Apps with JavaScript
Titanium: Develop Native Mobile Apps with JavaScriptTitanium: Develop Native Mobile Apps with JavaScript
Titanium: Develop Native Mobile Apps with JavaScript
 
Appcelerator OSS & Platform
Appcelerator OSS & PlatformAppcelerator OSS & Platform
Appcelerator OSS & Platform
 
Platform 4.0 Meetup Launch Event
Platform 4.0 Meetup Launch EventPlatform 4.0 Meetup Launch Event
Platform 4.0 Meetup Launch Event
 
Appcelerator Alloy MVC
Appcelerator Alloy MVCAppcelerator Alloy MVC
Appcelerator Alloy MVC
 
The Ultimate Titanium CLI Toolchain
The Ultimate Titanium CLI ToolchainThe Ultimate Titanium CLI Toolchain
The Ultimate Titanium CLI Toolchain
 
Getting ready for iOS 8 & iPhone 6
Getting ready for iOS 8 & iPhone 6Getting ready for iOS 8 & iPhone 6
Getting ready for iOS 8 & iPhone 6
 
Titanium Community Toolkit Showcase
Titanium Community Toolkit ShowcaseTitanium Community Toolkit Showcase
Titanium Community Toolkit Showcase
 
Titanium Alloy Tutorial
Titanium Alloy TutorialTitanium Alloy Tutorial
Titanium Alloy Tutorial
 
5 app alternatieven #AIB2013
5 app alternatieven #AIB20135 app alternatieven #AIB2013
5 app alternatieven #AIB2013
 
Apps voor kerken #Kerk2013
Apps voor kerken #Kerk2013Apps voor kerken #Kerk2013
Apps voor kerken #Kerk2013
 
TiNy #TiAppCamp
TiNy #TiAppCampTiNy #TiAppCamp
TiNy #TiAppCamp
 
Internetmarketing
InternetmarketingInternetmarketing
Internetmarketing
 
Alloy #DMC13
Alloy #DMC13Alloy #DMC13
Alloy #DMC13
 

Alloy Tips & Tricks #TiLon

  • 1. July 23rd, 2013 London Titanium Alloy Tips & Tricks FOKKE ZANDBERGEN app imagineer
  • 2.
  • 3. Alloy Tips & Tricks
  • 4. Compilation process Not your mother's MVC TSS XML Views + = Definition = Models Controllers Assets config.json
  • 5. Compilation process Not your mother's MVC Definition = Models Controllers Assets config.json JS
  • 6. Compilation process Not your mother's MVC Definition = Models Controllers Assets config.json JSCommonJS
  • 7. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.json JSCommonJS
  • 8. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.json JSCommonJS
  • 9. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.jsonAlloy.CFG JSCommonJS
  • 10. Compilation process Not your mother's MVC Collections Sync Store Models Controllers Assets config.jsonAlloy.CFG JSCommonJS
  • 11. 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;
  • 12. 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
  • 13.
  • 14. 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
  • 15. 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
  • 16. 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
  • 17. 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
  • 18. 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
  • 19. 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" });
  • 20. 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)
  • 21. __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
  • 22. 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
  • 23. 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);
  • 24. 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
  • 25. 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
  • 26. 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
  • 27. @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
  • 28. 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
  • 29. 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
  • 30. 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
  • 31. 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
  • 32. 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:
  • 33. 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)
  • 34. 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
  • 35. 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" />
  • 36. 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