koui /

Filename Size Date modified Message
examples
packages
src
tools
vendor
63 B
239 B
6.5 KB

koui

A knockoutjs-based UI toolkit.

About KnockoutJS

I'm not going to talk too much about KnockoutJS, other than that it is cool. It gives you 2-way bindings, and observable objects, making doing dynamic interfaces fun again.

About koui

koui (pronounced coo-ee), is a set of useful UI elements, that use KnockoutJS' binding and observable. They are designed to be easier to style than JqueryUI, and as such use HTML5 elements where appropriate. The intention is that whilst they might not all look 'the same' in every browser, they should at least look nice, and be functional.

So, there are some examples in the examples/ directory, that hopefully are fairly straightforward.

Installation

You just need to make sure that the js, css and img folders are in a place that your pages will be able to find them.

Usage

koui is totally implemented using KnockoutJS' binding. As such, all you need to do is have the relevant files available to the page, and then put the appropriate data binding in.

For instance, to turn an <input> widget into one that will have a datepicker associated with it, you just use:

<input data-bind="datepicker: sourceObservable">

Binding Types

autocomplete

A simple autocomplete widget that can be attached to an <input> element. That element must also have a value binding.

<input data-bind="value: source, autocomplete: listOfChoices">

In this case, listOfChoices must be an array of strings that will be searched for a match when data is entered into the input element.

Eventually, this will also be able to be a function, or a string (that will be assumed to be a JSON-source URI).

date

A nice date selector. By default, it will appear directly below the element it is bound to on the page, whenever the element gains focus. See also the time selector below.

There are lots of options available to this widget, that can be set using a dateOptions binding. The defaults are shown below.

{
   weekStartDay: "Monday",     // Note: must be in dayNames!
   showWeekNumbers: false,
   weekNumberTitle: "#",
   selectingCloses: true,
   dayNameLength: 2,
   yearRange: "-10:+10",       // (-nn:+nn); (nnnn:nnnn); (c-nn:c+nn); combinations

   maxDate: null,              // Convert these to Date objects if they aren't.
   minDate: '1978-01-01',
   defaultDate: null,          // 'today', Date()
   numberOfMonths: 1,          // Note: this cannot be changed at this stage.

   selectMonth: true,          // Note: This cannot be changed at this stage. 
   selectYear: true,           // Note: this cannot be changed at this stage.
   displayFormat: "%Y-%m-%d",  // Python-style formatting strings. Much nicer than the crappy PHP-style ones.

   // Allow for passing in monthNames/dayNames. This may go away and allow localisation at some stage.
   monthNames: [
     "January", "February", "March", "April", "May", "June", "July",
     "August", "September", "October", "November", "December"
   ],
   dayNames: [
     "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
   ]
 }

messages

This is a bit of an unusual way of using a binding. Instead of binding it to data, you bind it to some options. Then, you send messages using jQuery's event system. These messages will be displayed by an element within the bound element.

The simplest way to use it:

<div data-bind="messages: {}"></div>

This creates an ul element within (actually, after for now, see below), that will dynamically display any messages that reach the body element, or the viewModel that was active in the scope where the binding occurred.

For instance, you can have any element on the page trigger a message:

$('#element-id').trigger('message', {type: 'info', message: 'This is a message'});

You may also pass an expiry value.

The default options for this binding are:

{
  rootElement: 'body',          // A selector for the element that will listen.
  defaultType: 'info',          // If no type is passed in, use this.
  defaultExpiry: 4,             // # seconds: may also be 'click'
  messageTemplate: "...",       // The template that should be used to render the message view.
  messageFilter: ...,           // A callable that will be applied to filter messages for display.
                                // The default simply display every message.
  stopPropagation: false        // Don't pass messages up the chain.
}

You can pass any or all of these in to the binding declaration to set them.

A message looks like:

{
  type: 'css-class',
  message: 'Content to be displayed',
  expiry: 2
}

You can put any text into the first two fields: the type will be used to set the CSS class on the <li> element that is the representation of this message. message may also be an Array of strings. In that case, the strings will be joined by <br> elements. expiry is the number of seconds after which the message should disappear. A non-numeric value (or 0) means the message never expires, but can be clicked on to expire it.

You may also pass a simple string or Array of strings as a message: in that case the default type and expiry will be used to generate the message.

limitations

Due to an as-yet unresolved conflict between Knockout and jQuery, I cannot append the message display <ul> into the target element: it must be inserted after it into the DOM tree.

stopPropagation does not seem to work with any consistency just yet.

resize

Makes the element resizeable by one or more handles on it's edges.

To be resizeable, the object that is bound to it must have observables for the attributes that should be changeable:

  • top
  • left
  • height
  • width

In addition, you may also explicitly set the edges that will have handles.

The options available to this binding are:

{
  handles: none,          // n,s,e,w,ne,se,nw,sw,all,none
  containment: "parent"   // parent,document,<JQUERY_SELECTOR>
}

Limitations

Objects that are set to be contained within an element that has non-static width (ie, is based on the size of the view) will not automatically shrink if the window is resized.

time

A partner in crime to the date binding above, it can be used to show a time picker dropdown.

The nicest thing about this is that it can work in conjunction with a date picker, allowing you to have both bound to the same observable. They each only affect their relevant part of the data.

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.