97 |
98 |
99 |
--------------------------------------------------------------------------------
/docs/chaplin.application.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Application
4 | module_path: src/chaplin/application.coffee
5 | Chaplin: Application
6 | ---
7 |
8 | The **Chaplin.Application** object is a bootstrapper and a point of extension
9 | for the core modules of **Chaplin**: the **[Dispatcher](#initDispatcher)**, the
10 | **[Layout](#initLayout)**, the **[Router](#initRouter)**, and the
11 | **[Composer](#initComposer)**. The object can be extended by your application.
12 |
13 | The easiest way to get started is by extending `Chaplin.Application` with the
14 | bare essentials:
15 |
16 | ```coffeescript
17 | Chaplin = require 'chaplin'
18 | routes = require 'routes'
19 |
20 | module.exports = class MyApplication extends Chaplin.Application
21 | title: 'My Application'
22 | ```
23 | ```javascript
24 | var Chaplin = require('chaplin');
25 | var routes = require('routes');
26 |
27 | var MyApplication = Chaplin.Application.extend({
28 | title: 'My Application'
29 | });
30 |
31 | module.exports = MyApplication;
32 | ```
33 |
34 | Then you can pass options for router, dispatcher, etc. when starting the
35 | application:
36 |
37 | ```html
38 |
43 | ```
44 |
45 | For a complete example of this approach, see [Chaplin
46 | Boilerplate](https://github.com/chaplinjs/chaplin-boilerplate-plain).
47 |
48 | If you want to have more fine-grained control over application startup, you can
49 | override the various methods of `Chaplin.Application`. When overriding the
50 | `initialize` method, you should not call `super`, but do all the
51 | required calls in place or you run risk of initializing modules twice.
52 |
53 | Instead, the `initialize` method of your derived class must initialize
54 | the core modules by calling the `initRouter`, `initDispatcher`, `initLayout`
55 | and `initMediator` methods and then initiating navigation with `start`.
56 | For more details on proper initialization, see the original implementation in
57 | `Chaplin.Application`.
58 |
59 |
Properties
60 |
61 |
title
62 | This is the top-level title, handed to the layout module in the options hash.
63 | When using the [layout module](./chaplin.layout.html)’s default title template,
64 | the value for `title` will be appended to the subtitle passed to the
65 | `!adjustTitle` event in order to construct the document’s title.
66 |
67 | ```coffeescript
68 | # [...]
69 | class Application extends Chaplin.Application
70 | # [...]
71 | title: "Fruit"
72 |
73 | mediator.publish '!adjustTitle', 'Apple'
74 | # Document title is now "Apple — Fruit".
75 | ```
76 |
77 | ```javascript
78 | // [...]
79 | var Application = Chaplin.Application.extend({
80 | // [...]
81 | title: 'Fruit'
82 | });
83 | mediator.publish('!adjustTitle', 'Apple');
84 | // Document title is now "Apple — Fruit".
85 | ```
86 |
87 |
Methods
88 |
89 |
initDispatcher([options])
90 | Initializes the **dispatcher** module; forwards passed options to its constructor. See **[Chaplin.Dispatcher](./chaplin.dispatcher.html)** for more information.
91 |
92 | To replace the dispatcher with a derived class (possibly with various extensions), you’d override the `initDispatcher` method and construct the dispatcher class as follows:
93 |
94 | ```coffeescript
95 | # [...]
96 | Dispatcher = require 'dispatcher'
97 | class Application extends Chaplin.Application
98 | # [...]
99 | initDispatcher: (options) ->
100 | @dispatcher = new Dispatcher options
101 | ```
102 |
103 | ```javascript
104 | // [...]
105 | var Dispatcher = require('dispatcher');
106 | var Application = Chaplin.Application.extend({
107 | // [...]
108 | initDispatcher: function(options) {
109 | this.dispatcher = new Dispatcher(options);
110 | }
111 | });
112 | ```
113 |
114 |
initRouter(routes, [options])
115 | Initializes the **router** module; forwards passed options to its constructor. This starts the routing off by checking the current URL against all defined routes and executing the matched handler. See **[Chaplin.Router](./chaplin.router.html)** for more information.
116 |
117 | * **routes**
118 | The routing function that contains the match invocations, normally located in `routes.coffee`.
119 |
120 | To replace the router with a derived class (possibly with various extensions), you’d override the `initRouter` method and construct the router class as follows (ensuring to start the routing process as well):
121 |
122 | ```coffeescript
123 | # [...]
124 | Router = require 'router'
125 | class Application extends Chaplin.Application
126 | # [...]
127 | initRouter: (routes, options) ->
128 | @router = new Router options
129 |
130 | # Register any provided routes.
131 | routes? @router.match
132 | ```
133 |
134 | ```javascript
135 | // [...]
136 | var Router = require('router');
137 | var Application = Chaplin.Application.extend({
138 | // [...]
139 | initRouter: function(routes, options) {
140 | this.router = new Router(options);
141 |
142 | // Register any provided routes.
143 | if (routes != null) routes(this.router.match);
144 | }
145 | });
146 | ```
147 |
148 |
start()
149 | When all of the routes have been matched, call `start()` to begin monitoring routing events, and dispatching routes. Invoke this method after all of the components have been initialized as this will also match the current URL and dispatch the matched route.
150 |
151 | For example, if you want to fetch some data before application is started, you can do it like that:
152 |
153 | ```coffeescript
154 | # [...]
155 | class Application extends Chaplin.Application
156 | # [...]
157 | start: ->
158 | mediator.user.fetch().then =>
159 | super
160 | ```
161 |
162 | ```javascript
163 | // [...]
164 | var Application = Chaplin.Application.extend({
165 | // [...]
166 | start: function() {
167 | mediator.user.fetch().then(function() {
168 | Chaplin.Application.prototype.call(this);
169 | });
170 | }
171 | });
172 | ```
173 |
174 |
initComposer([options])
175 | Initializes the **composer** module; forwards passed options to its constructor. See **[Chaplin.Composer](./chaplin.composer.html)** for more information.
176 |
177 | To replace the layout with a derived class (possibly with various extensions), you'd override the `initComposer` method and construct the composer class as follows:
178 |
179 | ```coffeescript
180 | # [...]
181 | Composer = require 'composer'
182 | class Application extends Chaplin.Application
183 | # [...]
184 | initComposer: (options) ->
185 | @composer = new Composer options
186 | ```
187 |
188 | ```javascript
189 | // [...]
190 | var Composer = require('composer');
191 | var Application = Chaplin.Application.extend({
192 | // [...]
193 | initComposer: function(options) {
194 | this.composer = new Composer(options);
195 | }
196 | });
197 | ```
198 |
199 |
initLayout([options])
200 | Initializes the **layout** module, forwarding the options hash to its constructor. See **[Chaplin.Layout](./chaplin.layout.html)** for more information.
201 |
202 | To replace the layout with a derived class (possibly with various extensions), you'd override the `initLayout` method and construct the layout class as follows:
203 |
204 | ```coffeescript
205 | # [...]
206 | _ = require 'underscore'
207 | Layout = require 'layout'
208 | class Application extends Chaplin.Application
209 | # [...]
210 | initLayout: (options) ->
211 | @layout = new Layout _.defaults options, {@title}
212 | ```
213 |
214 | ```javascript
215 | // [...]
216 | var _ = require('underscore');
217 | var Layout = require('layout');
218 | var Application = Chaplin.Application.extend({
219 | // [...]
220 | initLayout: function(options) {
221 | this.layout = new Layout(_.defaults(options, {title: this.title}));
222 | }
223 | });
224 | ```
225 |
--------------------------------------------------------------------------------
/docs/chaplin.collection.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Collection
4 | module_path: src/chaplin/models/collection.coffee
5 | Chaplin: Collection
6 | ---
7 |
8 | `Chaplin.Collection` is an extension of `Backbone.Collection`. Major additions are disposal for improved memory management and the inclusion of the pub/sub pattern via the `Chaplin.EventBroker` mixin.
9 |
10 |
Methods
11 | All [`Backbone.Collection` methods](http://backbonejs.org/#Collection).
12 |
13 |
serialize()
14 | Memory-saving model serialization. Maps models to their attributes recursively. Creates an object which delegates to the original attributes when a property needs to be overwritten.
15 |
16 |
dispose()
17 | Announces to all associated views that the model is being disposed. Unbinds all the global event handlers and also removes all the event handlers on the `Model` module. Removes internal attribute hashes and event handlers. If supported by the runtime, the `Collection` is [frozen](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze) to prevent any changes after disposal.
18 |
19 | ## Usage
20 | To make use of Chaplin’s automatic memory management, use `subscribeEvent` instead of registering methods directly as pub/sub listeners. This forces the handler context so the handler might be removed again on model/collection disposal. It’s crucial to remove all references to model/collection methods to allow them to be garbage collected.
21 |
--------------------------------------------------------------------------------
/docs/chaplin.composer.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Composer
4 | module_path: src/chaplin/composer.coffee
5 | Chaplin: Composer
6 | ---
7 |
8 | ## Overview
9 |
10 | Grants the ability for views (and related data) to be persisted beyond one controller action.
11 |
12 | If a view is reused in a controller action method it will be instantiated and rendered if the view has not been reused in the current or previous action methods.
13 |
14 | If a view was reused in the previous action method and is not reused in the current action method, it will be disposed and removed from the DOM.
15 |
16 | ## Example
17 |
18 | A common use case is a login page. This login page is a simple centered form. However, the main application needs both header and footer controllers.
19 |
20 | The following is a sketch of this use case put into code:
21 |
22 | ```coffeescript
23 | # routes.coffee
24 | (match) ->
25 | match 'login', 'login#show'
26 | match '', 'index#show'
27 | match 'about', 'about#show'
28 |
29 |
30 | # controllers/login_controller.coffee
31 | Login = require 'views/login'
32 | class LoginController extends Chaplin.Controller
33 | show: ->
34 | # Simple view, just want to show the login screen
35 | @view = new Login()
36 |
37 |
38 | # controllers/site_controller.coffee
39 | Site = require 'views/site'
40 | Header = require 'views/header'
41 | Footer = require 'views/footer'
42 | class SiteController extends Chaplin.Controller
43 | beforeAction: ->
44 | # Reuse the Site view, which is a simple 3-row stacked layout that
45 | # provides the header, footer, and body regions
46 | @reuse 'site', Site
47 |
48 | # Reuse the Header view, which binds itself to whatever container
49 | # is exposed in Site under the header region
50 | @reuse 'header', Header, region: 'header'
51 |
52 | # Likewise for the footer region
53 | @reuse 'footer', Footer, region: 'footer'
54 |
55 |
56 | # controllers/index_controller.coffee
57 | Index = require 'views/index'
58 | SiteController = require 'controllers/site_controller'
59 | class IndexController extends SiteController
60 | show: ->
61 | # Instantiate this simple index view at the body region
62 | @view = new Index region: 'body'
63 |
64 |
65 | # controllers/about_me_controller.coffee
66 | AboutMe = require 'views/aboutme'
67 | SiteController = require 'controllers/site_controller'
68 | class AboutMeController extends SiteController
69 | show: ->
70 | # Instantiate this simple about me view at the body region
71 | @view = new AboutMe region: 'body'
72 | ```
73 |
74 | ```javascript
75 | // routes.js
76 | function(match) {
77 | match('login', 'login#show');
78 | match('', 'index#show');
79 | match('about', 'about#show');
80 | }
81 |
82 | // controllers/login_controller.js
83 | var Login = require('views/login');
84 | var LoginController = Chaplin.Controller.extend({
85 | show: function() {
86 | // Simple view, just want to show the login screen.
87 | this.view = new Login();
88 | }
89 | });
90 |
91 | // controllers/site_controller.js
92 | var Site = require('views/site');
93 | var Header = require('views/header');
94 | var Footer = require('views/footer');
95 | var SiteController = Chaplin.Controller.extend({
96 | beforeAction: function() {
97 | // Reuse the Site view, which is a simple 3-row stacked layout that
98 | // provides the header, footer, and body regions
99 | this.reuse('site', Site);
100 |
101 | // Reuse the Header view, which binds itself to whatever container
102 | // is exposed in Site under the header region
103 | this.reuse('header', Header, {region: 'header'});
104 |
105 | // Likewise for the footer region
106 | this.reuse('footer', Footer, {region: 'footer'});
107 | }
108 | });
109 |
110 | // controllers/index_controller.js
111 | var Index = require('views/index');
112 | var SiteController = require('controllers/site_controller');
113 | var IndexController = SiteController.extend({
114 | show: function() {
115 | // Instantiate this simple index view at the body region.
116 | this.view = new Index({region: 'body'});
117 | }
118 | });
119 |
120 | // controllers/about_me_controller.js
121 | var AboutMe = require('views/aboutme');
122 | var SiteController = require('controllers/site_controller');
123 | var AboutMeController = SiteController.extend({
124 | show: function() {
125 | // Instantiate this simple about me view at the body region.
126 | this.view = new AboutMe({region: 'body'});
127 | }
128 | });
129 | ```
130 |
131 | Given the controllers above here is what would happen each time the URL is routed:
132 |
133 | ```coffeescript
134 | route('login')
135 | # 'views/login' is initialized and rendered
136 |
137 | route('')
138 | # 'views/site' is initialized and rendered
139 | # 'views/header' is initialized and rendered
140 | # 'views/footer' is initialized and rendered
141 | # 'views/index' is initialized and rendered
142 | # 'views/login' is disposed
143 |
144 | route('about')
145 | # 'views/aboutme' is initialized and rendered
146 | # 'views/index' is disposed
147 |
148 | route('login')
149 | # 'views/login' is initialized and rendered
150 | # 'views/index' is disposed
151 | # 'views/footer' is disposed
152 | # 'views/header' is disposed
153 | # 'views/site' is disposed
154 | ```
155 |
156 |
157 | ## Long form
158 |
159 | By default, when a controller requests a view to be reused, the composer checks if the view instance exists and the new options are the same as before. If that is true the view is destroyed and reused.
160 |
161 | The following example shows another way to use the `compose` method to allow for just about anything. The check method should return true when it wishes the composition to be disposed and the `compose` method to be called. The composer will track and ensure proper disposal of whatever is returned from the compose method (be it a view or an object with properties that have dispose methods).
162 |
163 | ```coffeescript
164 | @reuse 'main-post',
165 | compose: ->
166 | @model = new Post {id: 42}
167 | @view = new PostView {@model}
168 | @model.fetch()
169 |
170 | check: -> @model.id isnt 42
171 | ```
172 |
173 | ```javascript
174 | this.reuse('main-post', {
175 | compose: function() {
176 | this.model = new Post({id: 42});
177 | this.view = new PostView({model: this.model});
178 | this.model.fetch();
179 | },
180 |
181 | check: function() {return this.model.id !== 42;}
182 | });
183 | ```
184 |
--------------------------------------------------------------------------------
/docs/chaplin.controller.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Controller
4 | module_path: src/chaplin/controllers/controller.coffee
5 | Chaplin: Controller
6 | ---
7 |
8 | Controllers are in charge of handling the lifecycle of specific models and their associated views. That is, they are responsible for both instantiating and connecting models/collections and their views, as well as disposing of them, before handing control over to another controller. There can be only one *current* controller, which provides the main view and represents the current URL. In addition, there can be several persistent controllers for overarching tasks, like for example a `SessionController`.
9 |
10 |
Methods
11 |
12 |
adjustTitle(subtitle)
13 | Adjusts document title to `subtitle - title`. A title template can be set when initializing the `Dispatcher`.
14 |
15 |
redirectTo(params, options)
16 |
17 | Simple proxy to `Chaplin.utils.redirectTo` that also does `this.redirected = true;`. See [`Chaplin.utils.redirectTo`](./chaplin.utils.html#redirectTo) for details.
18 |
19 |
dispose()
20 |
21 | Disposes all models and views on current `Controller` instance.
22 |
23 | ## Usage
24 |
25 | ### Structure
26 |
27 | By convention, there is one controller for each application module. A controller may provide methods for several actions like `index`, `show`, `edit`, etc. These action methods are called by the [Chaplin.Dispatcher](./chaplin.dispatcher.html) when an associated route matches.
28 |
29 | A controller is usually started following a route match. Each route entry points to one controller action, for example `likes#show`, which is the `show` action of the `LikesController`.
30 |
31 |
32 | ### Naming convention
33 |
34 | By default, all controllers must be placed in the `/controllers/` folder (the / stands for the root of the `baseURL` you have defined for your loader) and be suffixed with `_controller`. So for instance, the `LikesController` needs to be defined in the file `/controllers/likes_controller.js`.
35 |
36 | If you want to overwrite this behaviour, you can edit the `controller_path` and `controller_suffix` options in the options hash you pass to `Chaplin.Application.initDispatcher` or `Chaplin.Dispatcher.initialize`. See details in the `Chaplin.Dispatcher` [documentation](./chaplin.dispatcher.html#initialize).
37 |
38 |
39 | ### Before actions
40 |
41 | To execute code before the controller action is called, you can define a handler as the `beforeAction` property (e.g. to add access control checks).
42 |
43 |
44 | ### Example
45 |
46 | ```coffeescript
47 | define [
48 | 'controllers/controller',
49 | 'models/likes', # the collection
50 | 'models/like', # the model
51 | 'views/likes-view', # the collection view
52 | 'views/full-like-view' # the view
53 | ], (Controller, Likes, Like, LikesView, FullLikeView) ->
54 | 'use strict'
55 |
56 | class LikesController extends Controller
57 | beforeAction: (params, route) ->
58 | if route.action is 'show'
59 | @redirectUnlessLoggedIn()
60 |
61 | # Initialize method is empty here.
62 | index: (params) ->
63 | @collection = new Likes()
64 | @view = new LikesView {@collection}
65 |
66 | show: (params) ->
67 | @model = new Like id: params.id
68 | @view = new FullLikeView {@model}
69 | ```
70 |
71 | ```javascript
72 | define([
73 | 'controllers/controller',
74 | 'models/likes', // the collection
75 | 'models/like', // the model
76 | 'views/likes-view', // the collection view
77 | 'views/full-like-view' // the view
78 | ], function(Controller, Likes, Like, LikesView, FullLikeView) {
79 | 'use strict'
80 |
81 | var LikesController = Controller.extend({
82 | beforeAction: function() {
83 | this.redirectUnlessLoggedIn();
84 | },
85 |
86 | // Initialize method is empty here.
87 | index: function(params) {
88 | this.collection = new Likes();
89 | this.view = new LikesView({collection: this.collection});
90 | },
91 |
92 | show: function(params) {
93 | this.model = new Like({id: params.id});
94 | this.view = new FullLikeView({model: this.model});
95 | }
96 | });
97 | return LikesController;
98 | });
99 | ```
100 |
101 | ### Creating models and views
102 |
103 | A controller action should create a main view and save it as an instance property named `view`: `this.view = new SomeView(…)`.
104 |
105 | Normal models and collections should also be saved as instance properties so Chaplin can reach them.
106 |
107 | ### Controller disposal and object persistence
108 |
109 | By default a new controller is instantiated with every route match. That means models and views are disposed by default, even if the new controller is the same as the old controller.
110 |
111 | To persist models and views in a controlled way, it is recommended to use the [Chaplin.Composer](./chaplin.composer.html).
112 |
113 | Chaplin will automatically dispose all models and views that are properties of the controller instance. If you’re using the Composer to reuse models and views, you need to use local variables instead of controller properties. Otherwise Chaplin will dispose them with the controller.
114 |
115 | ### Including Controllers in the production build
116 |
117 | In your production environment, you may want to package your files together using a build tool like [r.js](http://requirejs.org/docs/optimization.html).
118 |
119 | Controllers are dynamically loaded from the `Chaplin.Dispatcher` using the `require()` method. Build tools like r.js can’t know about files that are lazy-loaded using `require()`. They only consider the static dependencies specified by `define()`.
120 |
121 | This means that build tools will ignore your controllers and won’t include them in your package. You need to include them manually, for instance with r.js:
122 |
123 | ```yaml
124 | paths:
125 | # ...
126 | modules:
127 | - name: 'application'
128 | - name: 'controllers/one_controller' # included manually into the build
129 | - name: 'controllers/another_controller' # same
130 | ```
131 |
--------------------------------------------------------------------------------
/docs/chaplin.dispatcher.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Dispatcher
4 | module_path: src/chaplin/dispatcher.coffee
5 | Chaplin: Dispatcher
6 | ---
7 |
8 | The `Dispatcher` sits between the router and the various controllers of your application. It listens for a routing event to occur and then:
9 |
10 | * disposes the previously active controller,
11 | * loads the target controller module,
12 | * instantiates the new controller, and
13 | * calls the target action.
14 |
15 |
Methods
16 |
17 |
initialize([options={}])
18 |
19 | * **options**:
20 | * **controllerPath** (default `'/controllers'`): the path to the folder for the controllers.
21 | * **controllerSuffix** (default `'_controller':`) the suffix used for controller files.
22 | Both of these options serve to generate path names for autoloading controller modules.
23 |
--------------------------------------------------------------------------------
/docs/chaplin.event_broker.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.EventBroker
4 | module_path: src/chaplin/lib/event_broker.coffee
5 | Chaplin: EventBroker
6 | ---
7 |
8 | The `EventBroker` offers an interface to interact with [Chaplin.mediator](./chaplin.mediator.html), meant to be used as a mixin.
9 |
10 |
Methods
11 |
12 |
publishEvent(event, arguments...)
13 | Publishes `event` globally, passing `arguments` along for interested subscribers.
14 |
15 |
subscribeEvent(event, handler)
16 | Subscribes the `handler` to the given `event`. If `handler` already subscribed to `event`, it will be removed as a subscriber and added afresh. This function is like `Chaplin.mediator.subscribe` except it cannot subscribe twice.
17 |
18 |
unsubscribeEvent(event, handler)
19 | Unsubcribe the `handler` from the `event`. This functions like `Chaplin.mediator.unsubscribe`.
20 |
21 |
unsubscribeAllEvents()
22 | Unsubcribe from any subscriptions made through this objects `subscribeEvent` method.
23 |
24 | ## Usage
25 |
26 | To give a class these pub/sub capabilities, you just need to make it extend `Chaplin.EventBroker`: `_.extend @prototype, EventBroker``_.extend(this.prototype, EventBroker)`.
27 |
--------------------------------------------------------------------------------
/docs/chaplin.layout.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Layout
4 | module_path: src/chaplin/views/layout.coffee
5 | Chaplin: Layout
6 | ---
7 |
8 | `Chaplin.Layout` is the top-level application “view”. It doesn't inherit from `Chaplin.View` but borrows some of its functionalities. It is tied to the `document` DOM element and handles app-wide events, such as clicks on application-internal links. Most importantly, when a new controller is activated, `Chaplin.Layout` is responsible for changing the main view to the view of the new controller.
9 |
10 |
Methods
11 |
12 |
initialize([options={}])
13 |
14 | * **options**:
15 | * **routeLinks** (default `'a, .go-to'`): the selector of elements you want to apply internal routing to. Set to false to deactivate internal routing. If `false`y, chaplin won’t route links at all.
16 | * **skipRouting** (default `'.noscript'`): if you want to skip the internal routing in some situation. Can take the following value:
17 | * selector: check if the activated link matches the selector. The default value is a selector and will prevent routing for any links with class `noscript`.
18 | * function: check the return value. Return `true` to continue routing, return `false` to stop routing. The path and the elements are passed as parameters. Example: `function(href, el) { return href == 'bla'; }`
19 | * false: never skip routing
20 | * **openExternalToBlank** (default `false`): whether or not links to external domains should open in a new window/tab.
21 | * **scrollTo** (default `[0, 0]`): the coordinates (x, y) you want to scroll to on view replacement. Set to *false* to deactivate it.
22 | * **titleTemplate** (default `_.template("<%= subtitle %> - <%= title %>")`): a function which returns the document title. Per default, it receives an object with the properties `title` and `subtitle`.
23 |
24 |
25 |
delegateEvents([events])
26 |
27 | A wrapper for `Backbone.View.delegateEvents`. See Backbone [documentation](http://backbonejs.org/#View-delegateEvents) for more details.
28 |
29 |
30 |
undelegateEvents()
31 |
32 | A wrapper for `Backbone.View.undelegateEvents`. See Backbone [documentation](http://backbonejs.org/#View-undelegateEvents) for more details.
33 |
34 |
35 |
hideOldView(controller)
36 |
37 | Hide the active (old) view on the `beforeControllerDispose` event sent by the dispatcher on route change and scroll to the coordinates specified by the initialize `scrollTo` option.
38 |
39 |
40 |
showNewView(context)
41 |
42 | Show the new view on the `dispatcher:dispatch` event sent by the dispatcher on route change.
43 |
44 |
45 |
adjustTitle(context)
46 |
47 | Adjust the title of the page based on the `titleTemplate` option. The `title` variable is the one defined at application level, the `subtitle` the one defined at controller level.
48 |
49 |
openLink(event)
50 |
51 | Open the `href` or `data-href` URL of a DOM element. When `openLink` is called it checks if the `href` is valid and runs the `skipRouting` function if set by the user. If the `href` is valid, it checks if it is an external link and depending on the `openExternalToBlank` option, opens it in a new window. Finally, if it is an internal link, it starts routing the URL.
52 |
53 | ## Usage
54 |
55 | ### App-wide events
56 |
57 | To register app-wide events, you can define them in the `events` hash. It works like `Backbone.View.delegateEvent` on the `document` DOM element.
58 |
59 |
60 | ### Route links internally
61 |
62 | If you want to route links internally, you can use the `events` hash with the `openLink` function like so:
63 |
64 | ```coffeescript
65 | events:
66 | 'click a': 'openLink'
67 | ```
68 |
69 | ```javascript
70 | events: {
71 | 'click a': 'openLink'
72 | }
73 | ```
74 |
75 | To open all external links (different hostname) in a new window, you can set `openExternalToBlank` to true when initializing `Chaplin.Layout` in your `Application`:
76 |
77 | ```coffeescript
78 | class MyApplication extends Chaplin.Application
79 | initialize: ->
80 | # ...
81 | @initLayout openExternalToBlank: true
82 | ```
83 |
84 | ```javascript
85 | var MyApplication = Chaplin.Application.extend({
86 | initialize: function() {
87 | // ...
88 | this.initLayout({openExternalToBlank: true});
89 | }
90 | });
91 | ```
92 |
93 | To add a custom check whether or not a link should be open internally, you can override the `isExternalLink` method:
94 |
95 | ```coffeescript
96 | class Layout extends Chaplin.Layout
97 | isExternalLink: (href) -> # some test on the href variable
98 | ```
99 |
100 | ```javascript
101 | var Layout = Chaplin.Layout.extend({
102 | isExternalLink: function(href) {} // some test on the href variable
103 | });
104 | ```
105 |
106 | ### View loading
107 |
108 | There is nothing to do, the Layout is listening to the `beforeControllerDispose` and `dispatcher:dispatch` and will trigger the function when a new route is called. If you are not happy with the site scrolling to the top of the page on each view load, you can set the `scrollTo` option when initializing `Chaplin.Layout` in your `Application`:
109 |
110 | ```coffeescript
111 | class MyApplication extends Chaplin.Application
112 |
113 | initialize: ->
114 | # ...
115 | @initLayout
116 | scrollTo: [10, 30] # will scroll to x=10px and y=30px.
117 | # OR
118 | scrollTo: false # deactivate the scroll
119 | ```
120 |
121 | ```javascript
122 | var MyApplication = Chaplin.Application.extend({
123 | initialize: function() {
124 | // ...
125 | this.initLayout({
126 | scrollTo: [10, 30] // will scroll to x=10px and y=30px.
127 | // OR
128 | scrollTo: false // deactivate the scroll
129 | });
130 | }
131 | });
132 | ```
133 |
--------------------------------------------------------------------------------
/docs/chaplin.mediator.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.mediator
4 | module_path: src/chaplin/mediator.coffee
5 | Chaplin: mediator
6 | ---
7 |
8 | It is one of the basic goals of Chaplin to enforce module encapsulation and independence and to direct communication through controlled channels. Chaplin’s `mediator` object is the enabler of this controlled communication. It implements the [Publish/Subscribe](http://en.wikipedia.org/wiki/Publish/subscribe) (pub/sub) pattern to ensure loose coupling of application modules, while still allowing for ease of information exchange. Instead of making direct use of other parts of the application, modules communicate by events, similar to how changes in the DOM are communicated to client-side code. Modules can listen for and react to events, but also publish events of their own to give other modules the chance to react. There are only three basic methods for this application-wide communication: `subscribe`, `unsubscribe` and `publish`.
9 |
10 | **Note:** If you want to give local pub/sub functionality to a class, take a look at the [EventBroker](./chaplin.event_broker.html).
11 |
12 |
Methods
13 |
14 |
subscribe(event, handler, [context])
15 |
16 | A wrapper for `Backbone.Events.on`. See Backbone [documentation](http://backbonejs.org/#Events-on) for more details.
17 |
18 |
unsubscribe([event], [handler], [context])
19 |
20 | A wrapper for `Backbone.Events.off`. See Backbone [documentation](http://backbonejs.org/#Events-off) for more details.
21 |
22 |
publish(event, [*args])
23 |
24 | A wrapper for `Backbone.Events.trigger`. See Backbone [documentation](http://backbonejs.org/#Events-trigger) for more details.
25 |
26 | ## Request-response methods
27 |
28 | Since Chaplin 0.11, Chaplin uses
29 | [request-response](http://en.wikipedia.org/wiki/Request-response)
30 | strategy for communication between application parts.
31 |
32 | Think of it as events, but with only one allowed handler which is at the
33 | same time required.
34 |
35 |
setHandler(handlerName, handler)
36 |
37 | Sets a handler function for particular `handlerName`.
38 |
39 |
execute(handlerName, [*args])
40 |
41 | Executes a handler function from particular `handlerName`. If the handler
42 | is not present, an error will be thrown.
43 |
44 | ## Usage
45 |
46 | In any module that needs to communicate with other modules, access to the application-wide pub/sub system can be gained by requiring `Chaplin` as a dependency. The mediator object is then available as `Chaplin.mediator`.
47 |
48 | ```coffeescript
49 | define ['chaplin', 'otherdependency'], (Chaplin, OtherDependency) ->
50 | ```
51 |
52 | ```javascript
53 | define(['chaplin', 'otherdependency'], function(Chaplin, OtherDependency) {})
54 | ```
55 |
56 | For example, if you have a session controller for logging in users, it will tell the mediator that the login occurred:
57 |
58 | ```coffeescript
59 | Chaplin.mediator.publish 'login', user
60 | ```
61 |
62 | ```javascript
63 | Chaplin.mediator.publish('login', user);
64 | ```
65 |
66 | The mediator will propagate this event to any module that was subscribed to the `'login'` event, as in this example:
67 |
68 | ```coffeescript
69 | Chaplin.mediator.subscribe 'login', @doSomething
70 | ```
71 |
72 | ```javascript
73 | Chaplin.mediator.subscribe('login', this.doSomething);
74 | ```
75 |
76 | Finally, if this module needs to stop listening for the login event, it can simply unsubscribe at any time:
77 |
78 | ```coffeescript
79 | Chaplin.mediator.unsubscribe 'login', @doSomething
80 | ```
81 |
82 | ```javascript
83 | Chaplin.mediator.unsubscribe('login', this.doSomething);
84 | ```
85 |
86 | To add some property on mediator, it is suggested to do it in `Application#initMediator`, when mediator is getting sealed:
87 |
88 | ```coffeescript
89 | class Application extends Chaplin.Application
90 | initMediator: ->
91 | Chaplin.mediator.prop = {hello: 'world'}
92 | super
93 | ```
94 |
95 | ```javascript
96 | var Application = Chaplin.Application.extend({
97 | initMediator: function() {
98 | Chaplin.mediator.prop = {hello: 'world'};
99 | this.constructor.__super__.initMediator.call(this);
100 | }
101 | })
102 | ```
103 |
--------------------------------------------------------------------------------
/docs/chaplin.model.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Model
4 | module_path: src/chaplin/models/model.coffee
5 | Chaplin: Model
6 | ---
7 |
8 | `Chaplin.Model` is an extension of `Backbone.Model`. Major additions are disposal for improved memory management and the inclusion of the pub/sub pattern via the `Chaplin.EventBroker` mixin.
9 |
10 |
Methods
11 | All `Backbone.Model` [methods](http://backbonejs.org/#Model).
12 |
13 |
getAttributes()
14 | An accessor for the model’s `attributes` property. The accessor can be overwritten by decorators to optionally perform any kind of processing of the data.
15 |
16 | **Note:** Pay attention to the fact that this returns the actual `attributes` object, not a serialization.
17 |
18 |
serialize()
19 | Memory-saving serializing of model attributes. Maps models to their attributes recursively. Creates an object which delegates to the original attributes when a property needs to be overwritten.
20 |
21 |
dispose()
22 | Sends a `'dispose'` event to all associated collections and views to announce that the model is being disposed. Unsubscribes all global and local event handlers and also removes all the event handlers that were subscribed to this model’s events. Removes the collection reference, internal attribute hashes and event handlers. On compliant runtimes the model is frozen to prevent any further changes to it, see [Object.freeze](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze).
23 |
24 | ## Usage
25 | To take advantage of the built in memory management, use `subscribeEvent` instead of registering model methods directly as handlers for global events. This ensures that the handler is added in a way that allows for automatic removal on model/collection disposal. It’s crucial to remove all references to model/collection methods to allow them to be garbage collected.
26 |
27 | The `SyncMachine` mixin for models simplifies the handling of asynchronous data fetching. Its functionality can be included with a simple `_.extend`: `_.extend @prototype, Chaplin.SyncMachine``_.extend(this.prototype, Chaplin.SyncMachine);`. To learn more about `SyncMachine`, see the [SyncMachine docs](./chaplin.sync_machine.html).
28 |
--------------------------------------------------------------------------------
/docs/chaplin.router.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.Router
4 | module_path: src/chaplin/lib/router.coffee
5 | Chaplin: Router
6 | ---
7 |
8 | This module is responsible for observing URL changes and matching them against a list of declared routes. If a declared route matches the current URL, a `router:match` event is triggered.
9 |
10 | `Chaplin.Router` is a replacement for [Backbone.Router](http://documentcloud.github.com/backbone/#Router) and does not inherit from it. It is a stand-alone implementation with several advantages over Backbone’s default. Why change the router implementation completely?
11 |
12 | In Backbone there are no controllers. Instead, Backbone’s `Router` maps routes to *its own methods*, serving two purposes and being more than just a router. Chaplin on the other hand delegates the handling of actions related to a specific route to controllers. Consequently, the router is really just a router. While the router has been rewritten for this purpose, Chaplin is using `Backbone.History` in the background. That is, Chaplin relies upon Backbone for handling hash URLs and interacting with the HTML5 History API (`pushState`).
13 |
14 | ## Declaring routes in the `routes` file
15 |
16 | By convention, all application routes should be declared in a separate file, the `routes` module. This is a simple module in which a list of `match` statements serve to declare corresponding routes. For example:
17 |
18 | ```coffeescript
19 | match '', 'home#index'
20 | match 'likes/:id', controller: 'controllers/likes', action: 'show'
21 | ```
22 |
23 | ```javascript
24 | match('', 'home#index');
25 | match('likes/:id', {controller: 'controllers/likes', action: 'show'});
26 | ```
27 |
28 | Ruby on Rails developers may find `match` intuitively familiar. For more information on its usage, [see below](#match). Internally, route objects representing each entry are created. If a route matches, a `router:match` event is published, passing the route object and a `params` hash which contains name-value pairs for named placeholder parts of the path description (like `id` in the example above), as well as additional GET parameters.
29 |
30 |
Methods
31 |
32 |
createHistory()
33 | Creates the `Backbone.History` instance.
34 |
35 |
startHistory()
36 | Starts `Backbone.History` instance. This method should be called only after all routes have been registered.
37 |
38 |
stopHistory()
39 | Stops the `Backbone.History` instance from observing URL changes.
40 |
41 |
match([pattern], [target], [options={}])
42 |
43 | Connects a path with a controller action.
44 |
45 | * **pattern** (String): A pattern to match against the current path.
46 | * **target** (String): Specifies the controller action which is called if this route matches. Optionally, replaced by an equivalent description through the `options` hash.
47 | * **options** (Object): optional
48 |
49 | The `pattern` argument may contain named placeholders starting with a colon (`:`) followed by an identifier. For example, `'products/:product_id/ratings/:id'` will match the paths
50 | `/products/vacuum-cleaner/ratings/jane-doe` as well as `/products/8426/ratings/72`. The controller action will be passed the parameter hash `{product_id: "vacuum-cleaner", id: "jane-doe"}` or `{product_id: "8426", id: "72"}`, respectively.
51 |
52 | The `target` argument is a string with the controller name and the action name separated by the `#` character. For example, `'likes#show'` denotes the `show` action of the `LikesController`.
53 |
54 | You can also equivalently specify the target via the `action` and `controller` properties of the `options` hash.
55 |
56 | The following properties of the `options` hash are recognized:
57 |
58 | * **params** (Object): Constant parameters that will be added to the params passed to the action and overwrite any values coming from a named placeholder
59 |
60 | ```coffeescript
61 | match 'likes/:id', 'likes#show', params: {foo: 'bar'}
62 | ```
63 |
64 | ```javascript
65 | match('likes/:id', 'likes#show', {params: {foo: 'bar'}});
66 | ```
67 |
68 | In this example, the `LikesController` will receive a `params` hash which has a `foo` property.
69 |
70 | * **constraints** (Object): For each placeholder you would like to put constraints on, pass a regular expression of the same name:
71 |
72 | ```coffeescript
73 | match 'likes/:id', 'likes#show', constraints: {id: /^\d+$/}
74 | ```
75 |
76 | ```javascript
77 | match('likes/:id', 'likes#show', {constraints: {id: /^\d+$/}});
78 | ```
79 |
80 | The `id` regular expression enforces the corresponding part of the path to be numeric. This route will match the path `/likes/5636`, but not `/likes/5636-icecream`.
81 |
82 | For every constraint in the constraints object, there must be a corresponding named placeholder, and it must satisfy the constraint in order for the route to match.
83 | For example, if you have a constraints object with three constraints: x, y, and z, then the route will match if and only if it has named parameters :x, :y, and :z and they all satisfy their respective regex.
84 |
85 | * **name** (String): Named routes can be used when reverse-generating paths using `Chaplin.utils.reverse` helper:
86 |
87 | ```coffeescript
88 | match 'likes/:id', 'likes#show', name: 'like'
89 | Chaplin.utils.reverse 'like', id: 581 # => likes/581
90 | ```
91 |
92 | ```javascript
93 | match('likes/:id', 'likes#show', {name: 'like'});
94 | Chaplin.utils.reverse('like', {id: 581}); // => likes/581
95 | ```
96 | If no name is provided, the entry will automatically be named by the scheme `controller#action`, e.g. `likes#show`.
97 |
98 |
route([path])
99 |
100 | Route a given path manually. Returns a boolean after it has been matched against the registered routes, corresponding to whether or not a match occurred. Updates the URL in the browser.
101 |
102 | * **path** can be an object describing a route by
103 | * **controller**: name of the controller,
104 | * **action**: name of the action,
105 | * **name**: name of a [named route](#match), can replace **controller** and **action**,
106 | * **params**: params hash.
107 |
108 | For routing from other modules, `Chaplin.utils.redirectTo` can be used. All of the following would be valid use cases.
109 |
110 | ```coffeescript
111 | Chaplin.utils.redirectTo 'messages#show', id: 80
112 | Chaplin.utils.redirectTo controller: 'messages', action: 'show', params: {id: 80}
113 | Chaplin.utils.redirectTo url: '/messages/80'
114 | ```
115 | ```javascript
116 | Chaplin.utils.redirectTo('messages#show', {id: 80});
117 | Chaplin.utils.redirectTo({controller: 'messages', action: 'show', params: {id: 80}});
118 | Chaplin.utils.redirectTo({url: '/messages/80'});
119 | ```
120 |
121 |
changeURL([url])
122 |
123 | Changes the current URL and adds a history entry without triggering any route actions.
124 |
125 | Handler for the globalized `router:changeURL` request-response handler.
126 |
127 | * **url**: string that is going to be pushed as the page’s URL
128 |
129 |
dispose()
130 |
131 | Stops the Backbone.history instance and removes it from the router object. Also unsubscribes any events attached to the Router. On compliant runtimes, the router object is frozen, see [Object.freeze](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/freeze).
132 |
133 | ## Request-response handlers of `Chaplin.Router`
134 |
135 | `Chaplin.Router` sets these global request-response:
136 |
137 | * `router:route path[, options]`
138 | * `router:reverse name, params[, options], callback`
139 | * `router:changeURL url[, options]`
140 |
141 | ## Usage
142 | `Chaplin.Router` is a dependency of [Chaplin.Application](./chaplin.application.html) which should be extended by your main application class. Within your application class you should initialize the `Router` by calling `initRouter` (passing your routes module as an argument) followed by `start`.
143 |
144 |
145 | ```coffeescript
146 | define [
147 | 'chaplin',
148 | 'routes'
149 | ], (Chaplin, routes) ->
150 | 'use strict'
151 |
152 | class MyApplication extends Chaplin.Application
153 | title: 'The title for your application'
154 |
155 | initialize: ->
156 | super
157 | @initRouter routes
158 | @start()
159 | ```
160 |
161 | ```javascript
162 | define([
163 | 'chaplin',
164 | 'routes'
165 | ], function(Chaplin, routes) {
166 | 'use strict';
167 |
168 | var MyApplication = Chaplin.Application.extend({
169 | title: 'The title for your application',
170 |
171 | initialize: function() {
172 | Chaplin.Application.prototype.initialize.apply(this, arguments);
173 | this.initRouter(routes);
174 | this.start();
175 | }
176 | });
177 |
178 | return MyApplication;
179 | });
180 | ```
181 |
--------------------------------------------------------------------------------
/docs/chaplin.support.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.support
4 | module_path: src/chaplin/lib/support.coffee
5 | Chaplin: support
6 | ---
7 |
8 | Provides feature detection that is used internally to determine the code path so that ECMAScript 5 features can be used if possible, without breaking compatibility with non-compliant engines.
9 |
10 |
propertyDescriptors
11 |
12 | Indicates if **[Object.defineProperty](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty)** is supported. It’s important to note that while Internet Explorer 8 has an implementation of `Object.defineProperty`, the method can only be used on DOM objects. This implementation takes this fact into account when determining support.
13 |
--------------------------------------------------------------------------------
/docs/chaplin.sync_machine.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.SyncMachine
4 | module_path: src/chaplin/lib/sync_machine.coffee
5 | Chaplin: SyncMachine
6 | ---
7 |
8 | The `Chaplin.SyncMachine` is a [finite-state machine](http://en.wikipedia.org/wiki/Finite-state_machine) for synchronization of models/collections. There are three states in which a model or collection can be in; unsynced, syncing, and synced. When a state transition (unsynced, syncing, synced, and syncStateChange) occurs, Backbone events are called on the model or collection.
9 |
10 |
Methods
11 |
12 |
syncState
13 |
14 | Returns the current synchronization state of the machine.
15 |
16 |
isUnsynced
17 |
18 | Returns a boolean to help determine if the model or collection is unsynced.
19 |
20 |
isSynced
21 |
22 | Returns a boolean to help determine if the model or collection is synced.
23 |
24 |
isSyncing
25 |
26 | Returns a boolean to help determine if the model or collection is currently syncing.
27 |
28 |
unsync
29 |
30 | Sets the state machine’s state to `unsynced`, then triggers any events listening for the `unsynced` and `syncStateChange` events.
31 |
32 |
beginSync
33 |
34 | Sets the state machine’s state to `syncing`, then triggers any events listening for the `syncing` and `syncStateChange` events.
35 |
36 |
finishSync
37 |
38 | Sets the state machine’s state to `synced`, then triggers any events listening for the `synced` and `syncStateChange` events.
39 |
40 |
abortSync
41 |
42 | Sets the state machine’s state back to the previous state if the state machine is in the `syncing` state. Then triggers any events listening for the previous state and `syncStateChange` events.
43 |
44 |
unsynced([callback], [context=this])
45 |
46 | `unsynced` is a convenience method which will execute a callback in a specified context whenever the state machine enters into the `unsynced` state.
47 |
48 | * **callback**: a function to be called when the `unsynced` event occurs
49 | * **context**: the context in which the callback should execute in. Defaults to `this`.
50 |
51 |
syncing([callback], [context=this])
52 |
53 | `syncing` is a convenience method which will execute a callback in a specified context whenever the state machine enters into the `syncing` state.
54 |
55 | * **callback**: a function to be called when the `syncing` event occurs
56 | * **context**: the context in which the callback should execute in. Defaults to `this`.
57 |
58 |
synced([callback], [context=this])
59 |
60 | `synced` is a convenience method which will execute a callback in a specified context whenever the state machine enters into the `synced` state.
61 |
62 | * **callback**: a function to be called when the `synced` event occurs
63 | * **context**: the context in which the callback should execute in. Defaults to `this`.
64 |
65 |
syncStateChange([callback], [context=this])
66 |
67 | `syncStateChange` is a convenience method which will execute a callback in a specified context whenever the state machine changes state.
68 |
69 | * **callback**: a function to be called when a state change occurs.
70 | * **context**: the context in which the callback should execute in. Defaults to `this`.
71 |
72 | ## Usage
73 |
74 | The `Chaplin.SyncMachine` is a dependency of `Chaplin.Model` and `Chaplin.Collection` and should be used for complex synchronization of models and collections. As an example, think of making requests to you own REST API or some third party web service.
75 |
76 | ```coffeescript
77 | class Model extends Chaplin.Model
78 | _.extend @prototype, Chaplin.SyncMachine
79 |
80 | initialize: ->
81 | super
82 | @on 'request', @beginSync
83 | @on 'sync', @finishSync
84 | @on 'error', @unsync
85 |
86 | ...
87 |
88 | # Will render view when model data will arrive from server.
89 | model = new Model
90 | view = new Chaplin.View {model}
91 | model.fetch().then view.render
92 | ```
93 |
94 | ```javascript
95 | var Model = Chaplin.Model.extend({
96 | initialize: function() {
97 | Chaplin.Model.prototype.initialize.apply(this, arguments);
98 | this.on('request', this.beginSync);
99 | this.on('sync', this.finishSync);
100 | this.on('error', this.unsync);
101 | }
102 | });
103 |
104 | _.extend(Model.prototype, Chaplin.SyncMachine);
105 |
106 | ...
107 |
108 | // Will render view when model data will arrive from server.
109 | var model = new Model;
110 | var view = new Chaplin.View({model: model});
111 | model.fetch().then(view.render);
112 | ```
113 |
114 | You can do the same to `Collection`.
115 |
116 | More complex example involving `Collection`:
117 |
118 | ```coffeescript
119 | define [
120 | 'chaplin'
121 | 'models/post' # Post model
122 | ], (Chaplin.Collection, Post) ->
123 |
124 | class Posts extends Chaplin.Collection
125 | # Initialize the SyncMachine
126 | _.extend @prototype, Chaplin.SyncMachine
127 |
128 | model: Post
129 |
130 | initialize: ->
131 | super
132 |
133 | # Will be called on every state change
134 | @syncStateChange announce
135 |
136 | @fetch()
137 |
138 | # Custom fetch method which warrents
139 | # the sync machine
140 | fetch: =>
141 |
142 | #Set the machine into `syncing` state
143 | @beginSync()
144 |
145 | # Do something interesting like calling
146 | # a 3rd party service
147 | $.get 'http://some-service.com/posts', @processPosts
148 |
149 | processPosts: (response) =>
150 | # Exit if for some reason this collection was
151 | # disposed prior to the response
152 | return if @disposed
153 |
154 | # Update the collection
155 | @reset(if response and response.data then response.data else [])
156 |
157 | # Set the machine into `synced` state
158 | @finishSync()
159 |
160 | announce: =>
161 | console.debug 'state changed'
162 | ```
163 |
164 | ```javascript
165 | define([
166 | 'chaplin',
167 | 'models/post' // Post model
168 | ], function(Chaplin.Collection, Post) {
169 |
170 | var Posts = Chaplin.Collection.extend({
171 | model: Post,
172 |
173 | initialize: function() {
174 | Chaplin.Collection.prototype.initialize.apply(this, arguments);
175 |
176 | // Initialize the SyncMachine
177 | _.extend(this, Chaplin.SyncMachine);
178 |
179 | // Will be called on every state change
180 | this.syncStateChange(this.announce.bind(this));
181 |
182 | this.fetch();
183 | },
184 |
185 | // Custom fetch method which warrents
186 | // the sync machine
187 | fetch: function() {
188 | // Set the machine into `syncing` state
189 | this.beginSync()
190 |
191 | // Do something interesting like calling
192 | // a 3rd party service
193 | $.get('http://some-service.com/posts', this.processPosts.bind(this))
194 | },
195 |
196 | processPosts: function(response) {
197 | // Exit if for some reason this collection was
198 | // disposed prior to the response
199 | if (this.disposed) return;
200 |
201 | // Update the collection
202 | this.reset((response && response.data) ? response.data : []);
203 |
204 | // Set the machine into `synced` state
205 | this.finishSync();
206 | },
207 |
208 | announce: function() {
209 | console.debug('state changed');
210 | }
211 | });
212 |
213 | return Posts;
214 | ```
215 |
--------------------------------------------------------------------------------
/docs/chaplin.utils.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Chaplin.utils
4 | module_path: src/chaplin/lib/utils.coffee
5 | Chaplin: utils
6 | ---
7 |
8 | Chaplin’s utils provide common functions for use throughout the project.
9 |
10 |
redirectTo([...params])
11 | Does a in-app redirect:
12 |
13 | 1. `redirectTo('messages#show', {id: 2})` — to a named route.
14 | 2. `redirectTo({url: 'messages/2'})` — to an URL.
15 | 3. `redirectTo({controller: 'messages', action: 'show', params: {id: 2}})` — etc.
16 |
17 | In the past, `!route:route[byName]` event was used for this purpose.
18 |
19 | To use replaceState and overwrite the current URL in the history you can use the
20 | third options arg that is forwarded to Backbone's `router.navigate`, e.g.
21 | `redirectTo('messages#show', {id: 2}, {replace: true})`
22 |
23 |
reverse(routeName[,...params])
24 | Returns the URL for a named route, appropriately filling in values given as `params`.
25 |
26 | For example, if you have declared the route
27 |
28 | ```coffeescript
29 | match '/users/:login/profile', 'users#show'
30 | ```
31 |
32 | ```javascript
33 | match('/users/:login/profile', 'users#show');
34 | ```
35 |
36 | you can use
37 |
38 | ```coffeescript
39 | Chaplin.utils.reverse 'users#show', login: 'paulmillr'
40 | # or
41 | Chaplin.utils.reverse 'users#show', ['paulmillr']
42 | ```
43 |
44 | ```javascript
45 | Chaplin.utils.reverse('users#show', {login: 'paulmillr'});
46 | // or
47 | Chaplin.utils.reverse('users#show', ['paulmillr']);
48 | ```
49 |
50 | to yield `'/users/paulmillr/profile'`.
51 |
52 |
beget(parent)
53 | * **returns a new object with `parent` as its prototype**
54 |
55 | A standard Javascript helper function that creates an object which delegates to another object. (see Douglas Crockford's *Javascript: The Good Parts* for more details). Uses [Object.create](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create) when available, and falls back to a polyfill if not present.
56 |
57 |
readonly(object, [*properties])
58 | * **returns true if successful, false if unsupported by the browser’s runtime**
59 |
60 | Makes properties of **object** read-only so they cannot be overwritten. The success of this operation depends on the current environment’s support.
61 |
62 |
getPrototypeChain(object)
63 | * **Object object**
64 |
65 | Gets the whole chain of prototypes for `object`.
66 |
67 |
getAllPropertyVersions(object, property)
68 | * **Object object**
69 | * **String property**
70 |
71 | Get all different value versions for `property` from `object`’s prototype chain. Usage:
72 |
73 | ```coffeescript
74 | class A
75 | prop: 1
76 | class B extends A
77 | prop: 2
78 |
79 | b = new B
80 | getAllPropertyVersions b, 'prop' # => [1, 2]
81 | ```
82 |
83 | ```javascript
84 | function A() {}
85 | A.prototype.prop = 1;
86 |
87 | function B() {}
88 | B.prototype = Object.create(A);
89 |
90 | var b = new B;
91 | getAllPropertyVersions(b, 'prop'); // => [1, 2]
92 | ```
93 |
94 |
111 | * **jQuery normalized event object `event`**
112 | * **returns boolean**
113 |
114 | Looks at an event object `event` to determine if the **shift**, **alt**, **ctrl**, or **meta** keys were pressed. Useful in link click handling (i.e. if you need ctrl-click or shift-click to open the link in a new window).
115 |
116 |
querystring.stringify(object)
117 | * **Object object**
118 |
119 | Returns a query string from a hash.
120 |
121 |