Permalink
Browse files

Update readme

  • Loading branch information...
Daniel Pupius
Daniel Pupius committed Mar 8, 2012
1 parent 909e36b commit 51a95db2fe1a10ca74024fc18804b708217ee1af
Showing with 55 additions and 23 deletions.
  1. +55 −23 README.md
View
@@ -8,7 +8,7 @@ It is intended to be used in conjunction with the [Closure Tools](http://code.go
Overview
--------
-At the core, a `surf.App` is responsible for managing multiple surfaces -- elements in the page -- and provides an interface for navigating between "screens". A screen is a configuration of the application's surfaces for a given state, the active screen defining the visible contents for each surface. Navigations are based on paths and should contain enough information to render a screen, this bakes perma-linking into the core of the API.
+At the core, a `surf.App` is responsible for managing multiple surfaces -- elements in the page -- and provides an interface for navigating between "screens". A screen is a configuration of the application's surfaces for a given state, the active screen defines the visible contents for each surface. Navigations are based on paths and should contain enough information to render a screen, this bakes perma-linking into the core of the API.
A simple application might contain only a single surface. Another app may contain surfaces for the main area, the sidebar, and the footer.
@@ -23,17 +23,49 @@ To ensure clarity, it may help to define some terms.
*page* - a HTML document that the browser loads.
-*single-page application* - a website that avoids full page loads, instead performing partial updates when new information is displayed. See [wikipedia](http://en.wikipedia.org/wiki/Single-page_application).
+*single-page application (SPA)* - a website that avoids full page loads, instead performing partial updates when new information is displayed. See [wikipedia](http://en.wikipedia.org/wiki/Single-page_application).
*application* - the root JavaScript construct, responsible for managing navigation and the current display.
-*surface* - an area of the page that can have information rendered into it. An application manages multiple surfaces.
+*surface* - an area of the page that can have information rendered into it. An application manages multiple surfaces.
*screen* - a configuration of surfaces, along with a JavaScript object to manage the lifetime. A screen corresponds to a navigation path and is equivalent to a *page* in the traditional web model.
+*screen factory* - factories are used to constructs screens, since multiple instances of the same screen may be rendered. For example, a product page can be rendered for many products. The screen factories are registered at application start up and will be called to with the navigation path. The first factory that can handle the navigation path will be used to construct the screen. (See API docs below for more details.)
+
*navigation* & *navigation path* - a navigation causes the transition to a new screen, flipping the content of the surfaces to display the content for the new screen. While a navigation is handled without a page load, navigation paths are used that mirror traditional browser navigation. The browser's location will be updated to match the navigation path.
+Life Cycle
+----------
+
+_Initialization:_
+
+1. Create an application object.
+2. Define surfaces that screens can render in, these correspond to elements on the page.
+3. Register screen factories that will be called when navigations occur.
+4. Call `app.init(opt_path)` with an optional path for initial navigation.
+
+_Navigation:_
+
+A navigation occurs when either `app.navigate('/somepath/')` is called directly or when a link is clicked whose `href` is a path underneath the base URL specified when the application was constructed. When either of these things happen:
+
+1. `surf.App.Topics.START` is dispatched to any subscribers.
+2. If there is an active screen its `beforeDeactivate()` method is called, if false is returned then the navigation is canceled.
+3.
+ a. If there is a cached screen which matches the navigation path exactly, then it will be used as the destination screen.
+ b. If there is no cached screen, each `matchesPath()` will be called on each screen factory until one returns true, indicating it can handle the navigation. `create()` will then be called on the factory which should return a new `Screen` instance. The new screen will then have `getSurfaceContent()` called for each surface in the application.
+4. If there was a previously started navigation, it will be canceled at this stage.
+5. `beforeFlip` will be called on the destination screen. This can return a deferred, which will pause the navigation until it is resolved.
+6. The surfaces will now be switched, if there is a transition function that was passed to `defineSurface` and it returns a deferred, the navigation will be paused until all surfaces' deferred have completed. This is useful for animations.
+7. Next, the page's title is updated and the browser location updated.
+8. `afterFlip()` is called on the new active screen.
+9. If the old screen is not cacheable, then it will be removed and its `dispose()` method called.
+
+
+If there are any errors the navigation will be canceled. `surf.App.Topics.END` will always be dispatched at the end of the navigation, regardless of whether it successfully executed all 9 steps above.
+
+
Basic Usage
-----------
@@ -62,7 +94,7 @@ setTimeout(function() {
Examples
--------
-`bin/serve-js.sh` will set up a [Plovr](http://www.plovr.com/) server on localhost:9810 that will serve compiled JS. The examples don't work well from a local file system, so you can either run them from a local apache/IIS installation, or if you have node installed try `node bin/static-file-server.js`, which will set up a server on localhost:9800 to serve the HTML.
+`bin/serve-js.sh` will set up a [Plovr](http://www.plovr.com/) server on localhost:9810 that will serve compiled JS. The examples don't work well from a local file system, so you can either run them from a local apache/IIS installation, or if you have node installed try `node bin/static-file-server.js`, which will set up a server on `localhost:9800` to serve the HTML.
`example/sample-app.html` is a really minimal example of a multi-surface app where a screen can set the content of multiple surfaces. The code is in `example/sample-app.js`.
@@ -80,34 +112,34 @@ The code is fully documented with expected parameters, type information, and fea
The main class that is responsible for managing navigations and history.
-`new surf.App(basePath, opt_defaultTitle)`
+`new surf.App(basePath, opt_defaultTitle)`
Constructs a new app. The basePath should be the root of the application, any paths that the app can handle must be subpaths. The default title is an optional fallback if the active screen doesn't specify its own title, if blank the app will fallback to document.title.
-`#defineSurface(id, opt_defaultContent, opt_transitionFn)`
+`#defineSurface(id, opt_defaultContent, opt_transitionFn)`
Defines a surface which the app should manage. The `id` should correspond to an element in the DOM. You can optionally specify default content that will be displayed if a screen doesn't provide content for the surface, and a transition function that will be used to flip a surface's children (default uses display='none' to hide the element). If you don't provide default content here, you can specify an element already in the DOM with the id of the surface plus '-default', e.g. 'mainarea-default', if neither are specified the surface will be blank unless the screen provides content.
-`#registerScreenFactory(factory)`
+`#registerScreenFactory(factory)`
Registers a screen factory with the app. When looking for a matching factory, they will be called in the order they were registered and the first to return true for `matchesPath()` will be used.
-`#init(opt_initialPath)`
+`#init(opt_initialPath)`
Initializes the application. If a path is specified an initial navigation is performed, replacing the current history state. Before calling `init()`, surfaces should have been defined and screen factories registered. Init must be called.
-`#navigate(path, opt_replaceHistory)`
+`#navigate(path, opt_replaceHistory)`
Starts a navigation to the given path. If a matching, cached screen is found it will be navigated too, otherwise a screen factory is looked for. If opt_replaceHistory is true, the navigation will replace the current entry on the history stack rather than pushing a new entry. `app.navigate()` returns a Deferred that will be called back once the navigation finishes, if the navigation fails its errback will be called.
-`#getActiveScreen()`
-Returns a reference to the currently active screen. If called during a navigation it refers to the screen being navigated _from_.
+`#getActiveScreen()`
+Returns a reference to the currently active screen. If called during a navigation it refers to the screen being navigated _from_.
### surf.ScreenFactory #
-Interface used by the app to construct screens. Multiple screen factories can be registered with an app. When navigating the app looks for the first factory that matches the requested path, and asks the factory to construct a `surf.Screen`.
+Interface used by the app to construct screens. Multiple screen factories can be registered with an app. When navigating the app looks for the first factory that matches the requested path, and asks the factory to construct a `surf.Screen`.
A concrete implementation is provided in `surf.RegExpScreenFactory(regExp, screenCtor)` that matches the path with a regular expression, and returns an instance of a Screen whose constructor was provided. An app may have a single screen factory that knows how to construct all possible screens, a screen factory for every screen type, or somewhere in between.
-`#matchesPath(path)`
-Whether to construct a screen for the path.
+`#matchesPath(path)`
+Whether to construct a screen for the path.
-`#create(path)`
+`#create(path)`
Create a new screen for the given path.
@@ -129,28 +161,28 @@ When another navigation occurs:
A concrete implementation is provided in `surf.NullScreen` that can be inherited from (for convenience) and individual methods overridden.
-`#isCacheable()`
+`#isCacheable()`
Whether the screen should be cached by the app. If false the screen will be disposed once it is deactivated. If true, the screen and its DOM will be kept around and can be flipped to quickly if navigated to again.
-`#getTitle()`
+`#getTitle()`
Gets the title which should be shown in the browser's title bar and in the history drop down.
-`#getSurfaceContent(surfaceId)`
+`#getSurfaceContent(surfaceId)`
Will be called for each surface in the app, the return value can be a string, an element, or null if the screen doesn't want to show anything for that surface.
-`#beforeFlip()`
+`#beforeFlip()`
Called before the screen is navigated to, whether it was just constructed or cached. If beforeFlip() returns a Deferred, the application won't finalize the navigation until the Deferred is resolved. This allows you to load data, for example, before the screen is made visible.
-`#afterFlip()`
+`#afterFlip()`
Called immediately after the screen has been navigated to. You know that the screen's elements are in the DOM and visible, should you need to do any initialization that requires measuring of elements.
-`#beforeDeactivate()`
+`#beforeDeactivate()`
Gives the screen a chance to cancel the navigation and stop itself from being deactivated. Can be used, for example, if the screen has unsaved state. Clean-up should not be preformed here, since the navigation may still be cancelled.
-`#deactivate()`
+`#deactivate()`
Called before the screen is navigated away from.
-`#dispose()`
+`#dispose()`
Called when the screen is being destroyed. Should do cleanup of event listeners, timers, requests, etc.
Licence

0 comments on commit 51a95db

Please sign in to comment.