ukijs blog

making web apps with uki

Mail.app on the web

with 12 comments

Mail.app

ukijs matured and I put it to the test. The idea for the test was to replicate Mac Mail.app core experience in the browser. With as much attention to details as possible and acceptable performance. The whole thing took me about 15 hours and 65kb of gziped code.

Motivation

We’ve seen a tremendous paradigm shift in the last year. Desktop experience on the web is going mainstream. The very existence of SproutCore and Cappuccino proves that you don’t have to sacrifice user experience on the web. And yes, you can write desktop class web apps without a team of 10 developers.

But there’re two things that I don’t like about these, otherwise awesome, frameworks. First they’re huge. They even brag about how huge they are: “…20k lines of code…“, “…100k lines of code…“. Second there’s a fair amount of “magic” involved in building your app with any of them. In case of Cappuccino you have a completely new language (Objective-J). SproutCore will “magically” create bindings and magically process your css.

What this basically means is that you have to do more: read more source, learn more conceptions and tools, support more code, fix more bugs. And your users have to wait more for your app to load. And I think we can do better. That’s why uki was started. The main goal and the promise behind the project is that you can create desktop-class apps with less code and less magic.

And so far uki is pretty close to the promise.
1. There’s no magic involved if you want to use the framework. Simply add a

<script>

tag to your page and you’re done. And you write in plain old javascript.
2. The whole framework gziped with images included (base64 encoded) weights 35kb. For comparison SproutCore is 150Kb without images or styles.

There’re two notable things about less code
First ukijs leaves to the browser what it can do by itself. Without any additional conceptions/code in-between. For example if you’re with SproutCore/Cappucchino and want to bind a focus event you’ll end up with something like this:

view.didBecomeFirstResponder = someHandler

while in uki it looks like:

view.bind('focus', handler)

or even simpler

views.focus(handler)

Second I do a fair amount of meta-programming. The same that you’ll see in jQuery core:

uki.each(['width', 'height',…, 'x', 'y', 'left', 'top'], function(index, attr) {…}, this);

How

Uki is an application framework. So there’s no HTML. All interfaces are build with javascript. And js will manage focus, selection, scrolling, layout, events for you.

There’re 4 common parts of an application: views, layouts, models and controllers.

Views are the basic building blocks of the interface. Uki comes with a collection of core views but you can add more or extend existing. Examples of views are: Slider, SplitPane or Table.

Layouts define how your views are placed on a page. Mostly the same way as HTML defines how your DOM nodes are placed within each other. But since you’re building the page from a complete interface components it is usually much much shorter. Look at the example of the main mail.app page.

Models store, load and transform the data from the server. You can stick to plain javascript objects but it is more convenient to add some behavior to your models. Like

message.markAsRead()

method. Models also trigger events when their data changes. So you can

message.bind('unread.change', handler)

Controllers bind everything together with events. You find views in the layout with css like selectors and then bind event handler to them. See the main page controller example.

Where to go next?

You can get more info at ukijs.org, get the sources of both the application and the framework. There’s a #ukijs channel on freenode.net irc and a google group.

Written by voloko

April 8, 2010 at 10:05 am

Posted in Uncategorized

0.1.0 release

leave a comment »

Ukijs 0.1.0 released. Grab it at http://static.ukijs.org/pkg/0.1.0/uki.js

What’s new

w3c drag and drop support. Uki views now support w3c drag and drop events, like ondragstart or drop. And it supports them in all browsers. See the screencast, demo and read the blog post to get more info on this feature.

multiselect attribute for List. All lists and tables now support selecting multiple rows with both keyboard and mouse (holding Shift or Ctrl/Option key). See the demo.

steps in slider. Slider supports stepped drag and drop with values attribute.

uki({ view: 'Slider', value: [1, 2, 3, 4, 5] ... }

will produce a slider with 5 separate handle positions. See the demo.

event wrapper. All events now wrapped into uki.dom.Event class. This means that you now longer need e.domEvent to access native event properties. Plus all events now have e.preventDefault() and e.stopPropagation() in all browsers.

long views renamed. Views with ‘Horizontal’ and ‘Vertical’ in name were renamed to shorter version with ‘H’ and ‘V’. So ‘HorizontalFlow’ is now ‘HFlow’.

And of course lot’s of minor tweaks and fixes.

Written by voloko

March 19, 2010 at 2:38 pm

Posted in Uncategorized

Tagged with , ,

Drag and drop in uki

with 11 comments

As of 0.1 ukijs gets support for drag and drop events based on w3c d&d specification (dragstart, drag, dragstop, dragover, dragenter, dragleave, drop). So in new browsers (FF3.5+, latest webkits) uki will use native events thus allowing to drag items within and outside of the browser window. For the rest of the browser crowd (IE, Opera, previous FF) uki will emulate exactly the same behavior within browser.

Screencast: drag and drop with uki from Volodya Kolesnikov on Vimeo.

Events

To make view draggable you have to mark it with draggable attribute. All uki views support it:

uki({ view: 'List', draggable: true ... })

Then add the dragstart event:

uki('List').draggstart(function(e) {
    // set the data that will be dragged 
    e.dataTransfer.setData('text/plain', this.selectedRows().join('\n'));
    // set the drag feedback image (both uki views 
    // and simple dom nodes are allowed)
    e.dataTransfer.setDragImage(uki(
        { view: 'Label', rect: '100 20', anchors: 'left top', inset: '0 5',
          background: 'cssBox(border: 1px solid #CCC;background:#EEF)',
          text: this.selectedRows().length + ' rows' }
     ), 10, 10);
     // set allowed affect to 'copy', 'move' etc
     e.dataTransfer.effectAllowed = 'copy';
});

For the drop targets you need to add dragover and drop events:

uki('[name=target]')
    .dragover(function(e) {   // required
        e.preventDefault();
        e.dataTransfer.dropEffect = 'copy'; // same as effectAllowed
    })
    .dragenter(function(e) {  // optional
        this.text('enter');
    })
    .dragleave(function(e) {  // optional
        this.text('leave');
    })
    .drop(function(e) {
        alert(e.dataTransfer.getData('text/plain'))
    });

See the demo

Written by voloko

March 16, 2010 at 11:20 am

Posted in Uncategorized

Tagged with , , , ,

Follow

Get every new post delivered to your Inbox.