Audible Artistry:

Electronic Introspection
The Shy Spectacular
Dance-pop mashup freak-fest
Antonio Carlos Jobim - Wave
Mike Laurence, Sax

Ventures:

(coming soon)

Programming:

trary
javascript column-view data browser
flex bench
interactive actionscript benchmarking tool

Miscellaneous Geekery:

max/pk
padKONTROL for Max

multitalented hoarder of soul power

trary: JSON implementation guide

Overview

Trary is a JavaScript data browser whose interface most resembles the Mac OS finder column view. It is designed to support object fields (attributes) as well as deeply nested data associations. The interface can be customized on a per-item basis with icons, CSS classes, CSS styles, and various JavaScript events.

Data Fundamentals

Trary currently loads data only in JSON format, though XML and possibly YAML will be implemented at a later date. Its interpretation of these data formats draws heavily from that of ActiveRecord's built-in serialization (a Ruby On Rails technology), which is itself sensible and fairly self-explanatory. There are a few syntactical rules, but you won't find any unwieldly schemas or DTDs waiting around to bungle up your data.

There are two essential data relationships for objects in Trary: fields and associations. Fields represent single nuggets of primitive data, such as names, IDs, and creation dates, whereas associations represent connections to other objects, the most common variants being 'has-one', 'has-many', and 'belongs-to' relationships.

Objects may also use one or more modifiers, which allow for customization of the interface on a per-item basis. These bear resemblance to fields in that they are single, primitive values, but there is a specific way of referencing them in each data format that distinguishes them from true data fields, which may actually have the same name (e.g., there is a 'class' modifier, but since it is referenced differently than data fields, you may still have a 'class' field in your objects).

Data Fields

Two types of fields bear particular importance within the context of Trary's interface:

  1. Label fields, which represent each object textually. The API allows you to custom define which fields you'd like to be used as labels, in an order of preference. By default, this order is 'label', then 'name', then 'title'.
  2. Value fields, which represent an underlying value for each object. Databases typically refer to rows and objects by unique identifiers, and these are usually not related to the name or label. Consequently, you may set up value fields in order to pass around these identifiers when objects are accessed in the interface. The default value fields are 'id' and then 'value'.

JSON notes:

Hashes (or "associative arrays") represent most fundamental data you will find in JSON, providing relationships between keys (a single column item) and values (information about that item, most often data that will be displayed in the next column when the item is clicked). But since objects are also hashes in JavaScript, many options for defining these relationships exist, including building custom class configurations. Nevertheless, defining variables in ordinary JSON is the most efficient method:

Example 1 (JSON)

var data = {
    'title': 'Multiply',
    'artist': 'Jamie Lidell',
    'sku': 'L-2005-41611',
    'year': 2005,
    'tracks': 10
};

As you can see, the above example contains only keys (fields) and their corresponding primitive values, omitting any relationships to other data. Because these keys are at the very top level, we actually won't have anything to select - all the viewer will display is the field values themselves. In order to have an 'album' to select, we'll need to nest the data one level deeper:

Example 2 (JSON)

var data = {
    'albums': {
        'title': 'Multiply',
        'artist': 'Jamie Lidell',
        'sku': 'L-2005-41611',
        'year': 2005,
        'tracks': 10
    }
};

Now the first column will contain an 'albums' entry, with associated fields being displayed in the second column if selected.

Modifiers

Like fields, modifiers are represented by primitive data (strings and numbers), but they are referenced differently in order to avoid conflicts with field names. Though the method of referencing varies by data format, their names and effects are the same. A few that show up in our examples are listed here:

  1. icon, which takes an image filename to be inserted to the left of its associated object. Note: the API allows you to set a default image path if you'd like.
  2. class, which adds the specified text to the CSS class of its associated object's HTML elements.
  3. style, which adds the specified text to the inline CSS style of its associated object's <TR> element.

Various JavaScript events and other features are accessible through modifiers; see the API for a complete reference.

JSON notes:

modifiers must be prefixed with an underscore when delivered via JSON. This is to distinguish them from any similarly-named data fields, and also constrain to the JavaScript rule that variables may contain no punctuation other than underscores. While this isn't an apparent issue when using hashes (where all keys are surrounded by quotes), it would be problematic for custom classes using regularly-named variables.

Example 3 (JSON)

var data = {
    'albums': {
        'title': 'Multiply',
        'artist': 'Jamie Lidell',
        'sku': 'L-2005-41611',
        'year': 2005,
        'tracks': 10,
        '_icon': 'icon_album.png',
        '_style': 'font-weight: bold'
    }
};

Data Relationships

The following example adds a single nested object to Example 2, adding a separate attribute set for the 'Artist' key which formerly only defined the artist's name:

JSON notes:

Nesting objects in JSON is quite easy, and fortunately it's no more difficult to build these relationships using Trary. Any key whose value is an object or array (as opposed to strings, numbers, or other primitives) will be interpreted as a relationship.

Note: listing fields alongside of relationships is not implemented yet, so you will not see the miscellaneous album data (such as SKU, etc.) underneath the 'artist' item.

Example 4 (JSON)

var data = {
    'albums': {
        'title': 'Multiply',
        'artist': {
            'name': 'Jamie Lidell',
            'website_url': 'http://www.jamielidell.com',
            'myspace_url': 'http://www.myspace.com/jamielidell',
            'date_of_birth': '09/18/1973',
            '_icon': 'icon_person.png'
        },
        'sku': 'L-2005-41611',
        'year': 2005,
        'tracks': 10,
        '_icon': 'icon_album.png',
        '_style': 'font-weight: bold'
    }
};

Note that 'artist' is now an associated object instead of a field, representing a has-one relationship. This is common for many musical albums, which usually have a principal artist. For has-many relationships, where a single object may relate to any number of child objects, we would have to use different notation. For example, we may want more detailed information about the tracks on the album than just their quantity, so we might turn them into a list of 'track' objects:

JSON notes:

For has-many relationships, arrays of primitives are acceptable, and will be listed with labels matching their values. This makes for efficient delivery of data when no additional fields or customization is required.

Example 5 (JSON)

var data = {
    'albums': {
        'title': 'Multiply',
        'artist': {
            'name': 'Jamie Lidell',
            'website_url': 'http://www.jamielidell.com',
            'myspace_url': 'http://www.myspace.com/jamielidell',
            'date_of_birth': '09/18/1973',
            '_icon': 'icon_person.png'
        },
        'sku': 'L-2005-41611',
        'year': 2005,
        'tracks': [
            'You Got Me Up',
            'Multiply',
            'When I Come Back Around',
            'A Little Bit More'
        ],
        '_icon': 'icon_album.png',
        '_style': 'font-weight: bold'
    }
};

In many cases, we will want to include additional information for leaf nodes (those items with no children), and can do so by using hashes in our list instead of just primitives:

Example 6 (JSON)

var data = {
    'albums': {
        'title': 'Multiply',
        'artist': {
            'name': 'Jamie Lidell',
            'website_url': 'http://www.jamielidell.com',
            'myspace_url': 'http://www.myspace.com/jamielidell',
            'date_of_birth': '09/18/1973',
            '_icon': 'icon_person.png'
        },
        'sku': 'L-2005-41611',
        'year': 2005,
        'tracks': [
            {'name': 'You Got Me Up', 'position': 1},
            {'name': 'Multiply', 'position': 2},
            {'name': 'When I Come Back Around', 'position': 3},
            {'name': 'A Little Bit More', 'position': 4}
        ],
        '_icon': 'icon_album.png',
        '_style': 'font-weight: bold'
    }
};

These objects can include all the usual attributes and modifiers on a per-item basis, along with their own nested relationships. But one issue does arise: what if we want to add attributes or modifiers to the relationship itself? For the Artist object, we were able to include an _icon modifier because there was only one hash, but an array of objects offers no such shortcut. The solution is to create a modifier hash adjacent to the relationship we wish to alter, using the same name but adding an underscore prefix (note: this prefix can be customized via the API). This ensures that the JSON data is still nested appropriately and that our interpretation engine will cooperate properly with Rails' serialization.

Example 7 (JSON)

var data = {
    'albums': {
        'title': 'Multiply',
        'artist': {
            'name': 'Jamie Lidell',
            'website_url': 'http://www.jamielidell.com',
            'myspace_url': 'http://www.myspace.com/jamielidell',
            'date_of_birth': '09/18/1973',
            '_icon': 'icon_person.png'
        },
        'sku': 'L-2005-41611',
        'year': 2005,
        'tracks': [
            {'name': 'You Got Me Up', 'position': 1},
            {'name': 'Multiply', 'position': 2},
            {'name': 'When I Come Back Around', 'position': 3},
            {'name': 'A Little Bit More', 'position': 4}
        ],
        '_tracks': {
            '_icon': 'icon_tracks.png'
        },
        '_icon': 'icon_album.png',
        '_style': 'font-weight: bold'
    }
};