User Interface

Basics

The user interface is described by one JSON tree, the framework will adapt the components to the platform you'll run you app on : Web, iOS, Android, Samsung TV, …

This tree defines every component the user is going to see or interact with : panels, lists, buttons, videos, and so on…

You've got a set of options to set the behavior of your UI components: autoInsert, autoShow, showOnFocus, hideOnBlur [link here]

Everything is event driven, so you have the ability to listen to any of the following events: insert, focus, select, show, hide. [link here]

Navigation

Navigation inside your app is controlled by the grid util.

UI Tree design

First, you need to extend the UI Tree class.


Joshfire.define(['joshfire/class', 'joshfire/tree.ui'], function(Class,UITree) {
  return Class(UITree, {
   
   buildTree: function() {
  ...
  return [{uielement}, {uielement},....]

Each UI element in you tree needs at least two properties:

Many UI elements also need a few display properties to be described : label, content, .. [..++precision..]

This dead simple UI tree will show an 'OK' button and an 'Hello World' panel.


return [
  {
    id:'mybutton',
    type:'button',
    label:'OK'
  },
  {
    id:'mypanel',
    type:'panel',
    content:'Hello World'
  }
}
];  

Your UI tree can be nested, an UI element can have one or many children, of any type. Useful for panels or lists. There is two ways to define the children of your UI element

1) Static


  {
    id:'mypanel',
    type:'panel',
    children:[
      {id:'childpanel1', type:'panel', content:'First'},
      {id:'childpanel2', type:'panel', content:'Second'}
    ]
  }

Bind to data root


  /* ... UI Tree ... */
  return [{
    id:'mypanel',
    type:'panel',
    children:[{id:'mylist', type:'list', dataPath:'/contacts'}]
  }];
  /* ... Data Tree ... */
  return [{
    id:'contacts',
    items:[{id:'1', label:'John'}, {id:'2', label:'Paul'}, {id:'3', label:'Peter'}]
  }];

Click here for details regarding advanced binding between UI & data trees

Binding an UI element to the data tree

An UI element can initialize or synchronize itself with your data tree.

dataPath

Specify a dataPath, and your element will be initialed with the corresponding data, and refresh itself whenever the data change.


  /* ... UI Tree ... */
  return [{
    id:'mypanel',
    type:'panel',
    children:[{id:'mylist', type:'list', dataPath:'/contacts'}]
  }];
  /* ... Data Tree ... */
  return [{
    id:'contacts',
    items:[{id:'1', label:'John'}, {id:'2', label:'Paul'}, {id:'3', label:'Peter'}]
  }];

uiDataMaster

uiDataMaster is the path of another ui element you want to listen to. Whenever it gets selected, the dataPath of your element gets changed accordingly.


  /* ... UI Tree ... */
   return [
  {
    id:'navigation', 
    type:'list', 
    autoShow:true,
    itemInnerTemplate:'<%=item.label%>',
    dataPath:'/categories'
  },
  {
    id:'subnav', 
    type:'list', 
    itemInnerTemplate:'<%=item.label%>',
    uiDataMaster:'/navigation'
  }
  ];
    
    /* ... Data Tree ... */
    return [
     {
          id:'categories',
          children:[
            {id:1, label:'Politics', children:[
          {id:11, label:'France'},
          {id:12, label:'US'},
          {id:13, label:'UK'}
        ]},
            {id:2, label:'Culture', children:[
          {id:21, label:'Books'},
          {id:22, label:'Movies'},
          {id:23, label:'Shows'}
        ]},
            {id:3, label:'Sports', children:[
          {id:31, label:'Football'},
          {id:32, label:'Tennis'},
          {id:33, label:'Rugby'}
        ]},
          ]
        }
    ];

Binding a ui element to another

uiMaster

Used by the Panel Manager component. In your UI element definition, specify a valid path as uiMaster, and your element will listen to events fired on its master.

Templating

Note: Most of your styling should be done using css.

Each UI Element has a default template, that you can overwrite to change the html structure.

We're using the underscore.js templating syntax, so you can use <% ... %> tags to insert javascript to be interpreted in your templates.

Depending on the element complexity, different templates can be instantiated:

Options

You also have a handful of options that let you customize the way your elements will behave. The more important are:

Click here for details on the available options

Events

You have the ability to plug yourself and do whatever you need when any event is fired on a specific UI element. Just declare a on[eventName] function, such as follow:


/* ... UI Tree ... */
 return [
{
  id:'navigation', 
  type:'list', 
  autoShow:true,
  itemInnerTemplate:'<%=item.label%>',
  dataPath:'/categories',
  onShow:function(){
    //list is being shown
  },
  onFocus:function(){
    //focus has been gained by this list
  },
  onSelect:function(){
    //List is selected: Mouse click, tv remote action, smartphone touch
  },
  onHide:function(){
    //list is being hidden
  }
},
{
  id:'subnav', 
  type:'list', 
  itemInnerTemplate:'<%=item.label%>',
  uiDataMaster:'/navigation'
}
];

Click here for a complete list of the events you may encounter.

Available components

Panel

This is the basic component. In fact you app will be inserted in a Panel.

Initialize it with {content:'Whatever html you want'} or {innerTemplate:function (){...}}

A Panel is a container, that you'll mainly use to wrap around other UI elements.

Click for details

Panel Manager

The Panel Manager component is used as a view switcher.

It listens to event from a parent UI element ({uiMaster:'/parent/path'}), and show one of its children at a time.

In the following pattern, we have a panel manager listening to a menu list.

When one item of the menu is selected, the panel shows the appropriate child panel, hiding every other.


return [
{
  id:'menu',
  type:'list',
  data:[
    {id:'panel1', label:'item #1'},
    {id:'panel2', label:'item #2'}
  ]
},
{
  id:'panelmgr',
  type:'panel.manager',
  uiMaster:'/menu',
  children:[
    {
      id:'panel1',
      type:'panel',
      content:'Panel #1'
    },
    {
      id:'panel2',
      type:'panel',
      content:'Panel #2'
    }
  ]
}
];  
Click for details

List

Well, this is a list of items.

In a browser, it will be anything from a dead-simple UL/LI to whatever you want (tweaking itemTemplate & itemInnerTemplate).

On smartphone, it will be native-looking scrollinglist, using iScroll.

Scrollability is on the way for the iOS adapter

Click for details

Button

Basically, a classic <input type='button' />, with a native fallback on mobile devices

Click for details

Video MediaElement

Your media player, html5, flash, ... the most suited on the platform you run your app

Click for details

Video

Video in a new window

Click for details

MediaControls

Your media controls: play, pause, stop, forward, …

Not implemented in ios adapter, as we're using the native video player, which comes with its own controls.

Click for details

Map

Actually the Map component is a abstraction of the Google Maps API.

It uses the Google Maps Javascript API V3, with a fallback on the Google Static Maps API if needed.

You're able to control the positioning of the map, the zoom level, ... and of course to pin point your data.

If you want to use an adapter for an other maps provider (Bing Maps, OpenStreet Maps, ..), feel free to contribute ! [link github]

Click for details