Uki is a JavaScript user interface toolkit for desktop-like web applications. It comes with a rich view-component library ranging from Sliders to Grids and SplitPanes.
uki({ view: 'Button', text: 'Click me', rect: '10 10 100 24' }).attachTo( window ); uki('Button[text^=Click]').click(function() { alert(this.text()); });
The Web should be simple. Adding a new library to your app should not require using a specific build process or learning a new language. It should be as simple as adding a <script> tag to your HTML. That’s exactly the way uki works. No frameworks to install, no dependencies to manage, no CSS to include. Simple.
I can imagine living in a fairy-tale world where any browser supports HTML 5 and there’s no such thing as IE6 :) Unfortunately, reality is different. I have to support all the browser flavors available, even the dinosaurs. That’s why uki works with IE6+, Opera 9+, FF 2+, Safari 3+, and Chrome. And it looks exactly the same on any of them.
One of the reasons uki appeared is that I had to create a 4000-row complex client-side-searchable table. Just rendering the table made any version of IE unresponsive for half a minute. Uki uses progressive rendering and can render 30k+-row lists and tables mostly instantly.
With all the images packed into it (not supported in IE6 and IE7), a gzipped uki build is under 30kb, and it’s a single HTTP request.
Creating a new component requires only one function to redeclare.
It’s great when you start building your whole app with uki. But sometimes you have to add a desktop-like experience to a working site. Say, adding a widget or a table to an existing design. While uki can occupy the whole browser window, it works perfectly well in a small <div> in your sidebar. Just use attachTo( myDiv ) for any widget you want to add.
Uki is written in plain JavaScript. It leverages well-known DOM and JS idioms such as CSS selectors, events and attributes. If you’ve ever used jQuery, learning uki won’t take long.
Uki doesn’t want to be a Jack-of-all-trades. It only does layout, but it does it well. You won’t find any AJAX or data-storage-layer code here.
HTML and CSS are great technologies, though you can’t lay everything out with them. There are things that require programmable layout calculations. Think of a toolbar, which should show a popup when some of the buttons don’t fit. Or a split pane. Or moving a slider bar on window resize. That’s the reason uki calculates view positions and sizes with JavaScript. Unfortunately, resizing everything with pure JS will make your layout slow as a turtle. So uki uses as much native browser layout as possible.
uki( { // create a split pane... view: 'SplitPane', rect: '1000 600', anchors: 'left top right bottom', handlePosition: 300, leftMin: 200, rightMin: 300, // ...with button on the left leftChildViews: { view: 'Button', rect: '10 10 280 24', anchors: 'top left right', text: 'Clear text field' }, // ...and a vertical split pane on the right... rightChildViews: [ { view: 'VerticalSplitPane', rect: '693 600', anchors: 'left top right bottom', vertical: true, // ...with text field in the top part topChildViews: { view: 'TextField', rect: '10 10 280 24', anchors: 'top left', value: '0', id: 'field' }, // ...and a slider in the bottom bottomChildViews: { view: 'Slider', rect: '10 10 673 24', anchors: 'top right left' } } ] }).attachTo( window, '1000 600' ); // on slider change update text field uki('SplitPane Slider').bind('change', function() { uki('TextField').value(this.value()) }); // on button click clear the text field uki('Button[text~="Clear"]').bind('click', function() { uki('#field').value('') // find by id });
results in ukijs.org/functional/splitPaneEx.html
uki({ view: 'Button', rect: '400px 40px 200px 24px', text: 'uki is awesome!' }).attachTo( document.getElementById('test'), '1000px 100px' ); uki('Button[text^=uki]').click(function() { alert('Hello world!'); }); uki( { view: "Button", text: "Click me", rect: "10 10 100 24" } ).attachTo( document.getElementById("test") ); uki("Button[text^=Click]").click( function() { alert(this.text()); } ); uki({ view: 'SplitPane', rect: '1000 600', anchors: 'left top right bottom', handlePosition: 300, autogrowLeft: false, leftMin: 300, rightMin: 300, leftChildViews: { view: 'Button', rect: '10 10 280 24', anchors: 'top left right', text: 'left pane' }, rightChildViews: [ { view: 'SplitPane', rect: '693 600', anchors: 'left top right bottom', vertical: true, topChildViews: { view: 'Button', rect: '10 10 280 24', anchors: 'top left', text: 'top pane' }, bottomChildViews: { view: 'Slider', rect: '10 10 673 24', anchors: 'top right left' } } ] }).attachTo( window, '1000 600' );
cd tests narwhal runner.js
And one more thing. Unobtrusive JavaScript is evil.