Frame

Frame is an extensive framework for the web written in JavaScript based on Objective-C and Apple's UIKit framework. While not identical it's heavily inspired by Apple's API design philosophy.

Getting started

Firing up the application stack

Every application starts with defining a new Frame.Application class and setting it to a special Frame attribute called application. The application class should implement at least one function didFinishLaunching. This method is called on your Application class once the DOM is ready and all javascript has been loaded and parsed.

Frame.application = Frame.Application.extend({
  didFinishLaunching: function() {
    // Method fired as soon as all javascript has been loaded and when the DOM is ready
  }
});

The Root ViewController and the View

A ViewController is a class which manages the relation between a view and any data there might be present. Any logic which doesn't belong directly within the view should be placed within the controller (ARGUMENTATION/CITATION NEEDED). Every ViewController has at least one view, the root view (accessed through controller.view). This view is created automatically once loadView is called (there's usually no need to call this method, it will be handled for you). Once the loadView method is called and the view has been initialized and created it will call the viewDidLoad method on your controller and you can add new custom views to the controller's root view with the addSubview(view) method.

The first ViewController of your application should be set as your application's rootViewController.

var MyView = Frame.View.extend({
  // Define a custom draw method
  draw: function() {
    this.$.html("Hello world");
  }
});

// Define the view controller
var BookViewController = new Frame.ViewController({
  viewDidLoad: function() {
    // Add subviews, events, etc.
    var myView = new MyView();
    this.view.addSubview(myView);
  }
});

Frame.application = Frame.Application.extend({
  didFinishLaunching: function() {
    this.rootViewController = new BookViewController();
  }
});

Once you've added a view to the controller's view it will automatically draw and insert the content in the parent's view. Under the hood it will call element.append unless the view has a the el property set. It will attempt to find the element within the parent, bind to it and render it's content to that element instead. Otherwise it will simply create a new <div/>.

Every view has a special $ attribute. This is the jQuery selector for your current view. Like in the example doing this.$.html("Hello world") will render "Hello world" to the view.

As your application grows you'll notice that you'll be needing more than just one controller. Within frame you can add child view controllers to any view controller with addChildViewConroller. This method will take care of calling loadView on the child view controller so the views of that controller can initialize.

Adding them is fairly straight forward. Let's assume the above book view controller and we'd like to add a search view controller:

viewDidLoad: function() {
  // Add subviews, events, etc
  var myView = new MyView();
  this.view.addSubview(myView);

  // Add the search view controller
  var searchViewController = new MySearchViewController(); // Binding to elements can still be done with the el option.
  // Add child controller
  this.addChildViewController(searchViewController);
  // Add the controllers view as subview
  this.view.addSubview(searchViewController.view);
}

As you can see Frame tries to do as much as trivial work for you as possible, however, view hierarchy needs be done manually. Frame doesn't know where you want to add your views and to which subview so even after adding the controller as a child controller, views still need to be added manually.

If you'd like to see more example, please check out the live examples or check the code

Frame API Reference

BasicObject

BasicObject is the lowest level object in the Frame framework. Everything inherits from this object. It is recommended that you use this object as you base object. Using BasicObject as your base objects allows you to fully empower your applications with an Objective-C like Key Value Coding (KVC) and Key Value Observing (KVO) methods.

BasicObject constructor / initialize new BasicObject([options])

Create a basic object with key value coding

BasicObject property Object.property('title')

Define a property on any BasicObject which are observable. Properties which are created through the property method are accessed with the normal dot notation.

BasicObject Key Value Observing object.addObserverForKey(observerOrKey, keyOrCallback, [options])

Add an observer for the given key. The observer will be notified once the given key/property has changed to a new value. The observer must implement the observeValueForKey(key, value) method, which will be passed the key which has changed with a new value. If you want to supply a callback instead of using an observer you may pass in the property for the observerOrKey and a callback as keyOrCallback. The optional options are currently not in use.

this.observeValueForKey = function(key, value) {
  alert("Key '"+key+"' changed value to '"+value+"'");
}
var book = new Frame.Model({
  title: "The Book Thief",
  author: "Markus Zusak"
});
book.addObserverForKey(this, 'title');
book.title = "The Thief of Books";
Try me

BasicObject valueForKey object.valueForKey(value_or_key, [key])

The valueForKey method is borrowed from Objective C. It's both a get and set accessor method for any given value on the object and respects KVO.

BasicObject gid object.gid

Every object that inherits from BasicObject has a global unique identifier. The BasicObject's gid is a unique number. You may if you wish set gid your self with the Frame.gid([prefix]) yourself. Using a prefex will result in identifiers such as view-8342.


Model

The Model object takes care of all the underlaying persistence and serialization of your data.

Model constructor new Model([attributes], [options])

Creating a new instance of any model is simple and straight forward. By calling new Model() a new instance of your object will be created. Optionally it can take an attribute object with attributes you wish to set on the model. Accessors will be created automatically.

var model = new Frame.Model({
  title: "My title",
  content: "My model with attributes"
})
    

toJSON model.toJSON()

Returns a copy of the attributes of the model which can be serialized by JSON.


    var book = new Frame.Model({
      title: "The Book Thief",
      author: "Markus Zusak"
    })

    JSON.stringify(book)
Try me

fetch model.fetch([parameters], [options])

Fetches the object from the specified url and attempts to serialize the attributes. Additional parameters may be send during fetch (these won't be serialized) and options can be set.

success

The success callback in the options hash are passed (data, textStatus, xhr)

var date = new Frame.Model({
  url: 'http://date.jsontest.com'
});
date.fetch({}, {
  success: function(data, textStatus, xhr) {
    alert(JSON.stringify(this));
  }
})
Try me

Please note that normally you would extend the model and set the on the object.