Jacob Waller: Webifying Titanium Development

Post on 09-May-2015

1.800 views 0 download

description

What if we could bring the good parts of web development to Titanium? I'm talking about the realtimeness of web development - changing files and being able to see results on the fly, both visually and regarding application logic. Compare it to Firebug's live CSS editing abilities and Chrome's live code changes. I'm also talking about bringing the beauty of web frameworks to Titanium - Stylus, SASS and Less for styling, CoffeeScript and its cousins to enhance development, Jasmine for testing, Backbone for MVC and jQuery and friends to simplify element creation, communication and handling. What if we could use all these techniques on top of Titanium to create native apps even faster and with better structure?The solution is Kranium - the result of merging Titanium with web development techniques, creating a cyborg which is greater than just the sum of its parts. It will significantly speed up development and styling, and is useful both for prototyping and production apps. It will be release under the MIT license during the conference. The session is meant as an introduction of Kranium for all Titanium developers, but will be especially thrilling for those with a web development background.

Transcript of Jacob Waller: Webifying Titanium Development

Kranium  Webifying  Titanium  Development  

Jacob  Waller  

+! +!+! →!

+

•  Webifying Titanium Development!

Kranium http://flic.kr/p/9wLZkJ!

"   Cross platform apps using javascript!

"   Shared business logic!

"   Native UI!

"   Device API:s!

Why cross-platform?

"   One codebase!

"   Faster development → cheaper development!

"   Less code → less bugs!

"   Focus on one language and one tool!

Why not cross-platform?

"   Potential bugs in cross-platform frameworks!

"   Somewhat harder stepping outside the box!

"   Might still need platform branching!

"   Less speed and more memory usage!

Cross Platform is Hard

"   iOS!

"   Objective-C!

"   XCode!

"   Android!

"   Java!

"   Eclipse!

Titanium takes the hit

http://flic.kr/p/91Zydu!

Cross Platform Medicine

"   Must use lowest common denominator!

"   Go with a low-level API!

"   Must focus on getting the “atoms” behave the same across platforms!

http://flic.kr/p/8dZbk4!

Low-level

Means powerful!

http://flic.kr/p/75b2DJ!

Low-level

Also means annoying to build large stuff!

http://flic.kr/p/5JDvZM!

Low-level

Is it therefore wrong?!

http://flic.kr/p/nyxCW!

NO

High-level

"   Low level building blocks let us build high-level abstractions!

"   Upon which we can build awesome stuff!

High-level

http://flic.kr/p/8ovJYH!

Titanium

"   Titanium Mobile has a low-level core API:s for each platform it supports!

"   Lets cover it in platform-independent high-level awesome-sauce!

But how?

http://flic.kr/p/9wfuUh!

Parallel

"   Web development has low-level API:s!

"   document.createElement!

"   element.style.backgroundColor!

Web development

if (el.addEventListener) { el.addEventListener("mouseover", myFunction, false); el.addEventListener("mouseout", myFunction, false);} else if (el.attachEvent) { el.attachEvent("onmouseover", myFunction); el.attachEvent("onmouseout", myFunction);} else { el.onmouseover = myFunction; el.onmouseout = myFunction;}

Used to be painful, slow and ugly!

Web development

Is now pleasant, quick and sexy!

$(el).bind("mouseover mouseout", myFunction);

Ecosystem

Titanium development

Used to be somewhat painful, slow and ugly!

var tabGroup = Ti.UI.createTabGroup(), win1 = Ti.UI.createWindow({ backgroundColor: '#ccc', barColor: '#00a', title: 'My window' }), tab1 = Ti.UI.createTab({ icon: 'path/to/my/icon', title: 'My tab', window: win1 }), label1 = Ti.UI.createLabel({ text: 'Hello world!', textAlign: 'center', color: '#333',

shadowColor: '#fff', shadowOffset: { y: -1, x: 0 }, font: { fontSize: 20, fontWeight: 'bold' } });win1.add(label1);label1.addEventListener('click', function(e){ alert('You clicked me!');});tabGroup.addTab(tab1);tabGroup.open();

Welcome Kranium

http://flic.kr/p/9wLZkJ!

Titanium development

Is now more pleasant, quick and sexy!

K({ type: 'tabgroup', tabs: [{ cls: 'myTab', window: { cls: 'myWindow', children: [{ text: 'Hello world!', cls: 'mylabel', click: function(){ alert('You clicked me!'); } }] } }]}).open();

Titanium development

Is now more pleasant, quick and sexy!

.myTab { icon: path/to/my/icon; }window { background-color: #ccc; bar-color: #00a;}.myLabel { text-align: center; color: #333; shadow-color: #fff; shadow-offset-y: -1; font-size: 20; font-weight: bold;}

Titanium development

With lots of possibilities!

K( type: "tabgroup" tabs: [ className: "myTab" window: className: "myWindow" children: [ text: "Hello world!" className: "mylabel" ] ]).open()

.myTab icon path/to/my/iconwindow background-color #ccc bar-color #00a.myLabel text-align center color #333 shadow-color #fff shadow-offset-y -1 font-size 20 font-weight bold

Stylus

Kranium "   Lovechild of the following stunning web frameworks:!

"   jQuery / Zepto!

"   Backbone!

"   Jade!

"   Livetanium / Livereload!

"   Sizzle / mini.js!

"   Jasmine!

"   JSS / Stylus / Sass / LESS!

"   JSConsole / Weinre!

http://bit.ly/3vVcI!

Comparison

jQuery / Zepto

"   Easy access selector engine!

$('.content > .label, .hello').text('hello!');$(el).find('.content');$('.content', el);

jQuery / Zepto

"   Chainable collections with helper functions!

$(el) .text('hey') .css({ color: '#f00' }) .parent('.row') .bind('click', onClick) .append(stuff);

jQuery / Zepto

"   Simplified API:s!

$.ajax({ type: 'GET', url: 'http://some/url', success: function(data, status, xhr){ alert(data); }});

Titanium

"   Let’s see how these look in the low-level Titanium API!

Titanium

"   Easy access selector engine?!

N/A

Titanium

"   Chainable collections with helper functions?!

el.text = 'hey';el.color = '#f00';var parent = el.getParent().getParent().children().filter(function(el){ return /(^|\s+)row(\s+|$)/.test(el.className);});parent.addEventListener('click', onClick);stuff.forEach(function(toAdd){ el.add(toAdd);});

Titanium

"   Simplified API:s?!

var xhr = Ti.Network.createHTTPClient();xhr.open('GET', 'http://some/url');xhr.onload = function(data, status, xhr){ alert(data);});xhr.send();

Kranium

"   Lets look at the same functionality using Kranium!

Kranium

"   Easy access selector engine!

$('.content > .label, .hello').text('hello!');$(el).find('.content');$('.content', el);

Kranium

"   Chainable collections with helper functions!

$(el) .text('hey') .css({ color: '#f00' }) .parent('.row') .bind('click', onClick) .append(stuff);

Kranium

"   Simplified API:s!

$.ajax({ type: 'GET', url: 'http://some/url', success: function(data, status, xhr){ alert(data); }});

Kranium

"   Tries to invent as few wheels as possible!

"   Instead piggyback on the ideas and momentum of existing great web frameworks!

http://bit.ly/bW1zP5!

What to piggyback? "   jQuery / Zepto!

"   Backbone!

"   Jade!

"   Livetanium / Livereload!

"   Sizzle / mini.js!

"   Jasmine!

"   JSS / Stylus / Sass / LESS!

"   JSConsole / Weinre!http://flic.kr/p/7dpmyF!

What IS Kranium?

"   A utility library to include in your app!

"   A command line program!

Utility library

"   Exposes a jQuery-like object called K (or $)!

"   Exposes Backbone integration!

"   Exposes Jade template engine!

"   Implements simple selector engine!

"   Implements enhanced styling!

"   Implements extendable modules!

Command line program

"   Built on NodeJS and NPM!

"   Initiates Kranium resources in project!

"   Pipes live updates!

"   Two-way console!

"   Jasmine reporter!

Template engine

"   DRY!

"   separated!

"   consise!

A great template engine is a huge help in keeping your code:!

Jade "   Lightweight!

"   Supports custom compilers!

"   Compiles templates to functions!

"   Beautiful syntax!

"   Consise!

"   In active development!

Jade example

// test.jadeview.board label.boardTitle Board view.boardMessages - each msg, user in users label.boardMessage= user + ' says ' + msg

K.jade('test.jade', { users: { jacob: 'yeah', david: 'what', conny: 'hi', aida: 'hello', calle: 'yup' }});

.board { top: 10; left: 10;}

.boardMessages { top: 30; layout: vertical;}

.boardMessage { height: 20; top: 10;}

.boardTitle { top: 0; height: auto; font-weight: bold;}

JSS

"   Great feature in theory - gives Separation of Concerns!

"   Hasn’t always been working well !

"   Not powerful and extendable enough!

KSS "   A styling layer implemented in the javascript

context!

"   Everything created using K function is styled appropriately!

"   Style based on Types, Classes and IDs!

"   Platform branching using psuedo selectors!

"   Variable evaluation!

KSS

label { color: #000; font-size: 16dp;}label:android { font-size: 17dp; text-align: left;}tableview:ios { style: Ti.UI.iPhone.TableViewStyle.GROUPED;}

KUI

"   Extendable UI Modules!

"   Simple Inheritance!

"   Automatic KSS loading!

http://flic.kr/p/6a3wzw!

Example

exports.Class = Label.extend({ className: "loginstatus", init: function(opts) { this.events = { app: { authchange: this.updateStatus.bind(this) } }; this._super.call(this, opts); this.updateStatus(); }, updateStatus: function(e) { this.el.text = "Logged " + (e && e.loggedIn ? "in" : "out"); }});

kui/loginstatus.js!

Example

.loginstatus { color: #f00;}

kui/loginstatus.kss!

Example

K({ type: 'window', children: [{ type: 'loggedinstatus' }]}).open();var i = 0;setInterval(function(){ Ti.App.fireEvent('authchange', { loggedIn: !!(++i % 2) });}, 1000);

app.js!

Example

K({ type: 'window', children: [{ top: 10, type: 'loggedinstatus' }, { bottom: 10, type: 'loggedinstatus' }]}).open();var i = 0;setInterval(function(){ Ti.App.fireEvent('authchange', { loggedIn: !!(++i % 2) });}, 1000);

app.js!

Backbone supplies structure to JavaScript-heavy

applications by providing models with key-value binding and custom events, collections with a rich

API of enumerable functions and views with declarative event handling...

Code walkthrough

// Define modelRowModel = Backbone.Model.extend({ type: 'tableviewrow'});// Define collectionRowCollection = Backbone.Collection.extend({ model: RowModel, comparator: function(model) { return model.get("title"); }});// Create todos collectiontodos = new RowCollection();todos.add([ { title: "An example todo" }, { title: "Another example todo" },]);// Create todolistvar todolist = K.create({ type: 'todolist', collection: todos});

// kui/todolist.jsexports.Class = BackboneView.extend({ type: 'tableview', editable: true, events: { click: function(e){ var model = todos.getByCid(e.rowData._modelCid); model.set({ hasCheck: !model.get('hasCheck') }); }, "delete": function(e){ var model = todos.getByCid(e.rowData._modelCid); todos.remove(model); } }});

exports.Class = Window.extend({ navBarHidden: true, init: function(o){

this.titleLabel = K.createLabel({ className: 'titleLabel' }); todos.bind('all', this.updateTitleLabel.bind(this)); this.updateTitleLabel();

this.children = [{ type: 'toolbar', className: 'todoToolbar', items: [{ type: 'textfield', className: 'todoInputTextField', events: { "return": function(e){ todos.add({ title: e.value }); } } }, 'spacer', this.titleLabel] }, todolist];

this._super(o); },

updateTitleLabel: function(){ var completed = todos.filter(function(m){ return m.get('hasCheck') }).length; this.titleLabel.text = completed + ' / ' + todos.length + ' todos'; }});

Polyfill missing UI "   Android lacks many simple UI modules!

"   Navbar!

"   TabbedBar!

"   ButtonBar!

"   Toolbar!

"   Extendable TabBar"

"   Kranium implements these!

Polyfill missing UI

Polyfill missing UI

Extend Base UI

K.createTableview({ pullToRefresh: true, refresh: function(){ K.ajax({ url: 'http://example.com/service.json', success: this.render }); }, render: function(data){ this.setData(data.rows.map(this.createRow)); }, createRow: function(o){ return K.createTableViewRow({ title: o.name }); }});

Livetanium

"   Kranium integrates Livetanium!

"   Gives you live updates of KSS style changes as well as module updates!

Jasmine

describe('Demo', function() { describe('Titanium Object', function(){ it('Ti == Titanium', function(){ expect(Titanium).toEqual(Ti); }); it('Ti.App', function(){ expect(Titanium).toBeDefined(); }); }); describe('TabGroup', function(){ it('Has tabgroup', function(){ expect(K('tabgroup').length).toBeGreaterThan(0); }); it('TabGroup.activeTab.title === "test"', function(){ expect(K('tabgroup').get(0).activeTab.title).toEqual("test"); }); });});

Console

Summary

"   Consists of a command line program and an includable library!

"   Ports the best web development libraries and technologies to Titanium!

"   Polyfills parts missing between platforms!

"   Helps you with your KISS:ing and keeps you DRY!

Available now

"   Currently in open beta!

"   Source under MIT License!

"   Hosted on GitHub!

"   Pull requests and co-maintainers welcome"

"   http://github.com/krawaller/kranium!

Available now

"   Beware!

"   There will be bugs!

"   API far from frozen!

Available now

"   Works best with iOS, but Android getting there!

"   CLI works best on Mac OSX!

"   Will be tested and fixed for Linux and Windows !

http://kraniumjs.com

Installation

"   1. Install NodeJS and NPM!

"   2. Run `npm install kranium`!

"   3. There is no step 3!

Questions?

http://flic.kr/p/7vB7fR!

+

Thank you

@litenjacob!jacob@krawaller.se!

jacob.waller@logica.com!

Go contribute please!

http://flic.kr/p/9C7DZZ!