Jacob Waller: Webifying Titanium Development
-
Upload
appcelerator-inc -
Category
Technology
-
view
1.800 -
download
0
description
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!
Go contribute please!
http://flic.kr/p/9C7DZZ!