marionette-amd-rails 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.md +42 -0
- data/lib/marionette-rails.rb +8 -0
- data/vendor/assets/javascripts/backbone.marionette.js +1033 -0
- metadata +62 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Godfrey Chan
|
2
|
+
Copyright (c) 2012 Andrey Subbotin
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
6
|
+
in the Software without restriction, including without limitation the rights
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
9
|
+
furnished to do so, subject to the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be included in
|
12
|
+
all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
marionette-amd-rails
|
2
|
+
====================
|
3
|
+
|
4
|
+
[](https://gemnasium.com/eploko/marionette-amd-rails)
|
5
|
+
|
6
|
+
This gem is a wrapper for the AMD version of Derick Bailey's [Backbone.Marionette](https://github.com/derickbailey/backbone.marionette) library. It vendors the javascript library code for use with Rails' asset pipeline (Rails 3.1+).
|
7
|
+
|
8
|
+
## Dependencies
|
9
|
+
|
10
|
+
[Backbone.Marionette](https://github.com/derickbailey/backbone.marionette) depends on Backbone (and Backbone's dependencies). These dependencies are not currently managed by the `marionette-rails` gem directly, because there exists multiple options to use Backbone with the Rails asset pipeline, such as [`backbone-on-rails`](https://github.com/meleyal/backbone-on-rails), [`backbone-rails`](https://github.com/aflatter/backbone-rails), [`rails-backbone`](https://github.com/codebrew/backbone-rails), just to name a few.
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Add it to your Gemfile:
|
15
|
+
|
16
|
+
group :assets do
|
17
|
+
# Your other asset gems (sass-rails, coffee-rails, etc)
|
18
|
+
|
19
|
+
gem 'marionette-amd-rails'
|
20
|
+
end
|
21
|
+
|
22
|
+
Load `backbone.marionette` module as a dependency when appropriate.
|
23
|
+
|
24
|
+
## Versioning
|
25
|
+
|
26
|
+
The gem will mirror the [Backbone.Marionette](https://github.com/derickbailey/backbone.marionette) versioning scheme. That is, version 0.8.2.* of `marionette-amd-rails` would vendor [Backbone.Marionette](https://github.com/derickbailey/backbone.marionette) v0.8.2.
|
27
|
+
|
28
|
+
## Contributing
|
29
|
+
|
30
|
+
For bugs in [Backbone.Marionette](https://github.com/derickbailey/backbone.marionette) itself, head over to their [issue tracker](https://github.com/derickbailey/backbone.marionette/issues). If you have a question, post it at [StackOverflow under the `backbone.marionette` tag](http://stackoverflow.com/questions/tagged/backbone.marionette).
|
31
|
+
|
32
|
+
For bugs in this gem distribution, use the [GitHub issue tracker](https://github.com/eploko/marionette-amd-rails/issues). If you could submit a pull request - that's even better!
|
33
|
+
|
34
|
+
## Donations
|
35
|
+
|
36
|
+
If you're using Marionette and you're finding that it is saving you time and effort, then please consider donating to the upstream [Backbone.Marionette](https://github.com/derickbailey/backbone.marionette) project.
|
37
|
+
|
38
|
+
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7SJHYWJ487SF4)
|
39
|
+
|
40
|
+
## License
|
41
|
+
|
42
|
+
This library is distributed under the MIT license. Please see the LICENSE file.
|
@@ -0,0 +1,1033 @@
|
|
1
|
+
// Backbone.Marionette v0.8.4
|
2
|
+
//
|
3
|
+
// Copyright (C)2012 Derick Bailey, Muted Solutions, LLC
|
4
|
+
// Distributed Under MIT License
|
5
|
+
//
|
6
|
+
// Documentation and Full License Available at:
|
7
|
+
// http://github.com/derickbailey/backbone.marionette
|
8
|
+
(function (root, factory) {
|
9
|
+
if (typeof exports === 'object') {
|
10
|
+
|
11
|
+
var jquery = require('jquery');
|
12
|
+
var underscore = require('underscore');
|
13
|
+
var backbone = require('backbone');
|
14
|
+
|
15
|
+
module.exports = factory(jquery, underscore, backbone);
|
16
|
+
|
17
|
+
} else if (typeof define === 'function' && define.amd) {
|
18
|
+
|
19
|
+
define(['jquery', 'underscore', 'backbone'], factory);
|
20
|
+
|
21
|
+
}
|
22
|
+
}(this, function ($, _, Backbone) {
|
23
|
+
|
24
|
+
Backbone.Marionette = (function(Backbone, _, $){
|
25
|
+
var Marionette = {};
|
26
|
+
|
27
|
+
Marionette.version = "0.8.4";
|
28
|
+
|
29
|
+
// Marionette.View
|
30
|
+
// ---------------
|
31
|
+
|
32
|
+
// The core view type that other Marionette views extend from.
|
33
|
+
Marionette.View = Backbone.View.extend({
|
34
|
+
// Get the template or template id/selector for this view
|
35
|
+
// instance. You can set a `template` attribute in the view
|
36
|
+
// definition or pass a `template: "whatever"` parameter in
|
37
|
+
// to the constructor options. The `template` can also be
|
38
|
+
// a function that returns a selector string.
|
39
|
+
getTemplateSelector: function(){
|
40
|
+
var template;
|
41
|
+
|
42
|
+
// Get the template from `this.options.template` or
|
43
|
+
// `this.template`. The `options` takes precedence.
|
44
|
+
if (this.options && this.options.template){
|
45
|
+
template = this.options.template;
|
46
|
+
} else {
|
47
|
+
template = this.template;
|
48
|
+
}
|
49
|
+
|
50
|
+
// check if it's a function and execute it, if it is
|
51
|
+
if (_.isFunction(template)){
|
52
|
+
template = template.call(this);
|
53
|
+
}
|
54
|
+
|
55
|
+
return template;
|
56
|
+
},
|
57
|
+
|
58
|
+
// Serialize the model or collection for the view. If a model is
|
59
|
+
// found, `.toJSON()` is called. If a collection is found, `.toJSON()`
|
60
|
+
// is also called, but is used to populate an `items` array in the
|
61
|
+
// resulting data. If both are found, defaults to the model.
|
62
|
+
// You can override the `serializeData` method in your own view
|
63
|
+
// definition, to provide custom serialization for your view's data.
|
64
|
+
serializeData: function(){
|
65
|
+
var data;
|
66
|
+
|
67
|
+
if (this.model) {
|
68
|
+
data = this.model.toJSON();
|
69
|
+
}
|
70
|
+
else if (this.collection) {
|
71
|
+
data = { items: this.collection.toJSON() };
|
72
|
+
}
|
73
|
+
|
74
|
+
data = this.mixinTemplateHelpers(data);
|
75
|
+
|
76
|
+
return data;
|
77
|
+
},
|
78
|
+
|
79
|
+
// Mix in template helper methods. Looks for a
|
80
|
+
// `templateHelpers` attribute, which can either be an
|
81
|
+
// object literal, or a function that returns an object
|
82
|
+
// literal. All methods and attributes from this object
|
83
|
+
// are copies to the object passed in.
|
84
|
+
mixinTemplateHelpers: function(target){
|
85
|
+
target = target || {};
|
86
|
+
var templateHelpers = this.templateHelpers;
|
87
|
+
if (_.isFunction(templateHelpers)){
|
88
|
+
templateHelpers = templateHelpers.call(this);
|
89
|
+
}
|
90
|
+
return _.extend(target, templateHelpers);
|
91
|
+
},
|
92
|
+
|
93
|
+
// Configure `triggers` to forward DOM events to view
|
94
|
+
// events. `triggers: {"click .foo": "do:foo"}`
|
95
|
+
configureTriggers: function(){
|
96
|
+
if (!this.triggers) { return; }
|
97
|
+
|
98
|
+
var triggers = this.triggers;
|
99
|
+
var that = this;
|
100
|
+
var triggerEvents = {};
|
101
|
+
|
102
|
+
// Allow `triggers` to be configured as a function
|
103
|
+
if (_.isFunction(triggers)){ triggers = triggers.call(this); }
|
104
|
+
|
105
|
+
// Configure the triggers, prevent default
|
106
|
+
// action and stop propagation of DOM events
|
107
|
+
_.each(triggers, function(value, key){
|
108
|
+
|
109
|
+
triggerEvents[key] = function(e){
|
110
|
+
if (e && e.preventDefault){ e.preventDefault(); }
|
111
|
+
if (e && e.stopPropagation){ e.stopPropagation(); }
|
112
|
+
that.trigger(value);
|
113
|
+
}
|
114
|
+
|
115
|
+
});
|
116
|
+
|
117
|
+
return triggerEvents;
|
118
|
+
},
|
119
|
+
|
120
|
+
delegateEvents: function(events){
|
121
|
+
events = events || this.events;
|
122
|
+
if (_.isFunction(events)){ events = events.call(this)}
|
123
|
+
|
124
|
+
var combinedEvents = {};
|
125
|
+
var triggers = this.configureTriggers();
|
126
|
+
_.extend(combinedEvents, events, triggers);
|
127
|
+
|
128
|
+
Backbone.View.prototype.delegateEvents.call(this, combinedEvents);
|
129
|
+
},
|
130
|
+
|
131
|
+
// Default `close` implementation, for removing a view from the
|
132
|
+
// DOM and unbinding it. Regions will call this method
|
133
|
+
// for you. You can specify an `onClose` method in your view to
|
134
|
+
// add custom code that is called after the view is closed.
|
135
|
+
close: function(){
|
136
|
+
if (this.beforeClose) { this.beforeClose(); }
|
137
|
+
|
138
|
+
this.unbindAll();
|
139
|
+
this.remove();
|
140
|
+
|
141
|
+
if (this.onClose) { this.onClose(); }
|
142
|
+
this.trigger('close');
|
143
|
+
this.unbind();
|
144
|
+
}
|
145
|
+
});
|
146
|
+
|
147
|
+
// Item View
|
148
|
+
// ---------
|
149
|
+
|
150
|
+
// A single item view implementation that contains code for rendering
|
151
|
+
// with underscore.js templates, serializing the view's model or collection,
|
152
|
+
// and calling several methods on extended views, such as `onRender`.
|
153
|
+
Marionette.ItemView = Marionette.View.extend({
|
154
|
+
constructor: function(){
|
155
|
+
var args = slice.call(arguments);
|
156
|
+
Marionette.View.prototype.constructor.apply(this, args);
|
157
|
+
|
158
|
+
_.bindAll(this, "render");
|
159
|
+
|
160
|
+
this.initialEvents();
|
161
|
+
},
|
162
|
+
|
163
|
+
// Configured the initial events that the item view
|
164
|
+
// binds to. Override this method to prevent the initial
|
165
|
+
// events, or to add your own initial events.
|
166
|
+
initialEvents: function(){
|
167
|
+
if (this.collection){
|
168
|
+
this.bindTo(this.collection, "reset", this.render, this);
|
169
|
+
}
|
170
|
+
},
|
171
|
+
|
172
|
+
// Render the view, defaulting to underscore.js templates.
|
173
|
+
// You can override this in your view definition.
|
174
|
+
render: function(){
|
175
|
+
var that = this;
|
176
|
+
|
177
|
+
var deferredRender = $.Deferred();
|
178
|
+
|
179
|
+
var beforeRenderDone = function() {
|
180
|
+
that.trigger("before:render", that);
|
181
|
+
that.trigger("item:before:render", that);
|
182
|
+
|
183
|
+
var deferredData = that.serializeData();
|
184
|
+
$.when(deferredData).then(dataSerialized);
|
185
|
+
}
|
186
|
+
|
187
|
+
var dataSerialized = function(data){
|
188
|
+
var asyncRender = that.renderHtml(data);
|
189
|
+
$.when(asyncRender).then(templateRendered);
|
190
|
+
}
|
191
|
+
|
192
|
+
var templateRendered = function(html){
|
193
|
+
that.$el.html(html);
|
194
|
+
callDeferredMethod(that.onRender, onRenderDone, that);
|
195
|
+
}
|
196
|
+
|
197
|
+
var onRenderDone = function(){
|
198
|
+
that.trigger("render", that);
|
199
|
+
that.trigger("item:rendered", that);
|
200
|
+
|
201
|
+
deferredRender.resolve();
|
202
|
+
}
|
203
|
+
|
204
|
+
callDeferredMethod(this.beforeRender, beforeRenderDone, this);
|
205
|
+
|
206
|
+
return deferredRender.promise();
|
207
|
+
},
|
208
|
+
|
209
|
+
// Render the data for this item view in to some HTML.
|
210
|
+
// Override this method to replace the specific way in
|
211
|
+
// which an item view has it's data rendered in to html.
|
212
|
+
renderHtml: function(data) {
|
213
|
+
var template = this.getTemplateSelector();
|
214
|
+
return Marionette.Renderer.render(template, data);
|
215
|
+
},
|
216
|
+
|
217
|
+
// Override the default close event to add a few
|
218
|
+
// more events that are triggered.
|
219
|
+
close: function(){
|
220
|
+
this.trigger('item:before:close');
|
221
|
+
Marionette.View.prototype.close.apply(this, arguments);
|
222
|
+
this.trigger('item:closed');
|
223
|
+
}
|
224
|
+
});
|
225
|
+
|
226
|
+
// Collection View
|
227
|
+
// ---------------
|
228
|
+
|
229
|
+
// A view that iterates over a Backbone.Collection
|
230
|
+
// and renders an individual ItemView for each model.
|
231
|
+
Marionette.CollectionView = Marionette.View.extend({
|
232
|
+
constructor: function(){
|
233
|
+
Marionette.View.prototype.constructor.apply(this, arguments);
|
234
|
+
|
235
|
+
_.bindAll(this, "addItemView", "render");
|
236
|
+
this.initialEvents();
|
237
|
+
},
|
238
|
+
|
239
|
+
// Configured the initial events that the collection view
|
240
|
+
// binds to. Override this method to prevent the initial
|
241
|
+
// events, or to add your own initial events.
|
242
|
+
initialEvents: function(){
|
243
|
+
if (this.collection){
|
244
|
+
this.bindTo(this.collection, "add", this.addChildView, this);
|
245
|
+
this.bindTo(this.collection, "remove", this.removeItemView, this);
|
246
|
+
this.bindTo(this.collection, "reset", this.render, this);
|
247
|
+
}
|
248
|
+
},
|
249
|
+
|
250
|
+
// Handle a child item added to the collection
|
251
|
+
addChildView: function(item){
|
252
|
+
var ItemView = this.getItemView();
|
253
|
+
return this.addItemView(item, ItemView);
|
254
|
+
},
|
255
|
+
|
256
|
+
// Loop through all of the items and render
|
257
|
+
// each of them with the specified `itemView`.
|
258
|
+
render: function(){
|
259
|
+
var that = this;
|
260
|
+
var deferredRender = $.Deferred();
|
261
|
+
var promises = [];
|
262
|
+
var ItemView = this.getItemView();
|
263
|
+
|
264
|
+
if (this.beforeRender) { this.beforeRender(); }
|
265
|
+
this.trigger("collection:before:render", this);
|
266
|
+
|
267
|
+
this.closeChildren();
|
268
|
+
|
269
|
+
if (this.collection) {
|
270
|
+
this.collection.each(function(item){
|
271
|
+
var promise = that.addItemView(item, ItemView);
|
272
|
+
promises.push(promise);
|
273
|
+
});
|
274
|
+
}
|
275
|
+
|
276
|
+
deferredRender.done(function(){
|
277
|
+
if (this.onRender) { this.onRender(); }
|
278
|
+
this.trigger("collection:rendered", this);
|
279
|
+
});
|
280
|
+
|
281
|
+
$.when.apply(this, promises).then(function(){
|
282
|
+
deferredRender.resolveWith(that);
|
283
|
+
});
|
284
|
+
|
285
|
+
return deferredRender.promise();
|
286
|
+
},
|
287
|
+
|
288
|
+
// Retrieve the itemView type, either from `this.options.itemView`
|
289
|
+
// or from the `itemView` in the object definition. The "options"
|
290
|
+
// takes precedence.
|
291
|
+
getItemView: function(){
|
292
|
+
var itemView = this.options.itemView || this.itemView;
|
293
|
+
|
294
|
+
if (!itemView){
|
295
|
+
var err = new Error("An `itemView` must be specified");
|
296
|
+
err.name = "NoItemViewError";
|
297
|
+
throw err;
|
298
|
+
}
|
299
|
+
|
300
|
+
return itemView;
|
301
|
+
},
|
302
|
+
|
303
|
+
// Render the child item's view and add it to the
|
304
|
+
// HTML for the collection view.
|
305
|
+
addItemView: function(item, ItemView){
|
306
|
+
var that = this;
|
307
|
+
|
308
|
+
var view = this.buildItemView(item, ItemView);
|
309
|
+
this.bindTo(view, "all", function(){
|
310
|
+
|
311
|
+
// get the args, prepend the event name
|
312
|
+
// with "itemview:" and insert the child view
|
313
|
+
// as the first event arg (after the event name)
|
314
|
+
var args = slice.call(arguments);
|
315
|
+
args[0] = "itemview:" + args[0];
|
316
|
+
args.splice(1, 0, view);
|
317
|
+
|
318
|
+
that.trigger.apply(that, args);
|
319
|
+
});
|
320
|
+
|
321
|
+
this.storeChild(view);
|
322
|
+
this.trigger("item:added", view);
|
323
|
+
|
324
|
+
var viewRendered = view.render();
|
325
|
+
$.when(viewRendered).then(function(){
|
326
|
+
that.appendHtml(that, view);
|
327
|
+
});
|
328
|
+
|
329
|
+
return viewRendered;
|
330
|
+
},
|
331
|
+
|
332
|
+
// Build an `itemView` for every model in the collection.
|
333
|
+
buildItemView: function(item, ItemView){
|
334
|
+
var view = new ItemView({
|
335
|
+
model: item
|
336
|
+
});
|
337
|
+
return view;
|
338
|
+
},
|
339
|
+
|
340
|
+
// Remove the child view and close it
|
341
|
+
removeItemView: function(item){
|
342
|
+
var view = this.children[item.cid];
|
343
|
+
if (view){
|
344
|
+
view.close();
|
345
|
+
delete this.children[item.cid];
|
346
|
+
}
|
347
|
+
this.trigger("item:removed", view);
|
348
|
+
},
|
349
|
+
|
350
|
+
// Append the HTML to the collection's `el`.
|
351
|
+
// Override this method to do something other
|
352
|
+
// then `.append`.
|
353
|
+
appendHtml: function(collectionView, itemView){
|
354
|
+
collectionView.$el.append(itemView.el);
|
355
|
+
},
|
356
|
+
|
357
|
+
// Store references to all of the child `itemView`
|
358
|
+
// instances so they can be managed and cleaned up, later.
|
359
|
+
storeChild: function(view){
|
360
|
+
if (!this.children){
|
361
|
+
this.children = {};
|
362
|
+
}
|
363
|
+
this.children[view.model.cid] = view;
|
364
|
+
},
|
365
|
+
|
366
|
+
// Handle cleanup and other closing needs for
|
367
|
+
// the collection of views.
|
368
|
+
close: function(){
|
369
|
+
this.trigger("collection:before:close");
|
370
|
+
this.closeChildren();
|
371
|
+
Marionette.View.prototype.close.apply(this, arguments);
|
372
|
+
this.trigger("collection:closed");
|
373
|
+
},
|
374
|
+
|
375
|
+
closeChildren: function(){
|
376
|
+
if (this.children){
|
377
|
+
_.each(this.children, function(childView){
|
378
|
+
childView.close();
|
379
|
+
});
|
380
|
+
}
|
381
|
+
}
|
382
|
+
});
|
383
|
+
|
384
|
+
// Composite View
|
385
|
+
// --------------
|
386
|
+
|
387
|
+
// Used for rendering a branch-leaf, hierarchical structure.
|
388
|
+
// Extends directly from CollectionView and also renders an
|
389
|
+
// an item view as `modelView`, for the top leaf
|
390
|
+
Marionette.CompositeView = Marionette.CollectionView.extend({
|
391
|
+
constructor: function(options){
|
392
|
+
Marionette.CollectionView.apply(this, arguments);
|
393
|
+
this.itemView = this.getItemView();
|
394
|
+
},
|
395
|
+
|
396
|
+
// Retrieve the `itemView` to be used when rendering each of
|
397
|
+
// the items in the collection. The default is to return
|
398
|
+
// `this.itemView` or Marionette.CompositeView if no `itemView`
|
399
|
+
// has been defined
|
400
|
+
getItemView: function(){
|
401
|
+
return this.itemView || this.constructor;
|
402
|
+
},
|
403
|
+
|
404
|
+
// Renders the model once, and the collection once. Calling
|
405
|
+
// this again will tell the model's view to re-render itself
|
406
|
+
// but the collection will not re-render.
|
407
|
+
render: function(){
|
408
|
+
var that = this;
|
409
|
+
var compositeRendered = $.Deferred();
|
410
|
+
|
411
|
+
var modelIsRendered = this.renderModel();
|
412
|
+
$.when(modelIsRendered).then(function(html){
|
413
|
+
that.$el.html(html);
|
414
|
+
that.trigger("composite:model:rendered");
|
415
|
+
that.trigger("render");
|
416
|
+
|
417
|
+
var collectionIsRendered = that.renderCollection();
|
418
|
+
$.when(collectionIsRendered).then(function(){
|
419
|
+
compositeRendered.resolve();
|
420
|
+
});
|
421
|
+
});
|
422
|
+
|
423
|
+
compositeRendered.done(function(){
|
424
|
+
that.trigger("composite:rendered");
|
425
|
+
});
|
426
|
+
|
427
|
+
return compositeRendered.promise();
|
428
|
+
},
|
429
|
+
|
430
|
+
// Render the collection for the composite view
|
431
|
+
renderCollection: function(){
|
432
|
+
var collectionDeferred = Marionette.CollectionView.prototype.render.apply(this, arguments);
|
433
|
+
collectionDeferred.done(function(){
|
434
|
+
this.trigger("composite:collection:rendered");
|
435
|
+
});
|
436
|
+
return collectionDeferred.promise();
|
437
|
+
},
|
438
|
+
|
439
|
+
// Render an individual model, if we have one, as
|
440
|
+
// part of a composite view (branch / leaf). For example:
|
441
|
+
// a treeview.
|
442
|
+
renderModel: function(){
|
443
|
+
var data = {};
|
444
|
+
data = this.serializeData();
|
445
|
+
|
446
|
+
var template = this.getTemplateSelector();
|
447
|
+
return Marionette.Renderer.render(template, data);
|
448
|
+
}
|
449
|
+
});
|
450
|
+
|
451
|
+
// Region
|
452
|
+
// ------
|
453
|
+
|
454
|
+
// Manage the visual regions of your composite application. See
|
455
|
+
// http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
|
456
|
+
Marionette.Region = function(options){
|
457
|
+
this.options = options || {};
|
458
|
+
|
459
|
+
_.extend(this, options);
|
460
|
+
|
461
|
+
if (!this.el){
|
462
|
+
var err = new Error("An 'el' must be specified");
|
463
|
+
err.name = "NoElError";
|
464
|
+
throw err;
|
465
|
+
}
|
466
|
+
|
467
|
+
if (this.initialize){
|
468
|
+
this.initialize.apply(this, arguments);
|
469
|
+
}
|
470
|
+
};
|
471
|
+
|
472
|
+
_.extend(Marionette.Region.prototype, Backbone.Events, {
|
473
|
+
|
474
|
+
// Displays a backbone view instance inside of the region.
|
475
|
+
// Handles calling the `render` method for you. Reads content
|
476
|
+
// directly from the `el` attribute. Also calls an optional
|
477
|
+
// `onShow` and `close` method on your view, just after showing
|
478
|
+
// or just before closing the view, respectively.
|
479
|
+
show: function(view, appendMethod){
|
480
|
+
this.ensureEl();
|
481
|
+
|
482
|
+
this.close();
|
483
|
+
this.open(view, appendMethod);
|
484
|
+
|
485
|
+
this.currentView = view;
|
486
|
+
},
|
487
|
+
|
488
|
+
ensureEl: function(){
|
489
|
+
if (!this.$el || this.$el.length === 0){
|
490
|
+
this.$el = this.getEl(this.el);
|
491
|
+
}
|
492
|
+
},
|
493
|
+
|
494
|
+
// Override this method to change how the region finds the
|
495
|
+
// DOM element that it manages. Return a jQuery selector object.
|
496
|
+
getEl: function(selector){
|
497
|
+
return $(selector);
|
498
|
+
},
|
499
|
+
|
500
|
+
// Internal method to render and display a view. Not meant
|
501
|
+
// to be called from any external code.
|
502
|
+
open: function(view, appendMethod){
|
503
|
+
var that = this;
|
504
|
+
appendMethod = appendMethod || "html";
|
505
|
+
|
506
|
+
$.when(view.render()).then(function () {
|
507
|
+
that.$el[appendMethod](view.el);
|
508
|
+
if (view.onShow) { view.onShow(); }
|
509
|
+
if (that.onShow) { that.onShow(view); }
|
510
|
+
view.trigger("show");
|
511
|
+
that.trigger("view:show", view);
|
512
|
+
});
|
513
|
+
},
|
514
|
+
|
515
|
+
// Close the current view, if there is one. If there is no
|
516
|
+
// current view, it does nothing and returns immediately.
|
517
|
+
close: function(){
|
518
|
+
var view = this.currentView;
|
519
|
+
if (!view){ return; }
|
520
|
+
|
521
|
+
if (view.close) { view.close(); }
|
522
|
+
this.trigger("view:closed", view);
|
523
|
+
|
524
|
+
delete this.currentView;
|
525
|
+
},
|
526
|
+
|
527
|
+
// Attach an existing view to the region. This
|
528
|
+
// will not call `render` or `onShow` for the new view,
|
529
|
+
// and will not replace the current HTML for the `el`
|
530
|
+
// of the region.
|
531
|
+
attachView: function(view){
|
532
|
+
this.currentView = view;
|
533
|
+
}
|
534
|
+
});
|
535
|
+
|
536
|
+
// Layout
|
537
|
+
// ------
|
538
|
+
|
539
|
+
// Formerly known as Composite Region.
|
540
|
+
//
|
541
|
+
// Used for managing application layouts, nested layouts and
|
542
|
+
// multiple regions within an application or sub-application.
|
543
|
+
//
|
544
|
+
// A specialized view type that renders an area of HTML and then
|
545
|
+
// attaches `Region` instances to the specified `regions`.
|
546
|
+
// Used for composite view management and sub-application areas.
|
547
|
+
Marionette.Layout = Marionette.ItemView.extend({
|
548
|
+
constructor: function () {
|
549
|
+
this.vent = new Backbone.Marionette.EventAggregator();
|
550
|
+
Backbone.Marionette.ItemView.apply(this, arguments);
|
551
|
+
this.regionManagers = {};
|
552
|
+
},
|
553
|
+
|
554
|
+
render: function () {
|
555
|
+
this.initializeRegions();
|
556
|
+
return Backbone.Marionette.ItemView.prototype.render.call(this, arguments);
|
557
|
+
},
|
558
|
+
|
559
|
+
close: function () {
|
560
|
+
this.closeRegions();
|
561
|
+
Backbone.Marionette.ItemView.prototype.close.call(this, arguments);
|
562
|
+
},
|
563
|
+
|
564
|
+
// Initialize the regions that have been defined in a
|
565
|
+
// `regions` attribute on this layout. The key of the
|
566
|
+
// hash becomes an attribute on the layout object directly.
|
567
|
+
// For example: `regions: { menu: ".menu-container" }`
|
568
|
+
// will product a `layout.menu` object which is a region
|
569
|
+
// that controls the `.menu-container` DOM element.
|
570
|
+
initializeRegions: function () {
|
571
|
+
var that = this;
|
572
|
+
_.each(this.regions, function (selector, name) {
|
573
|
+
var regionManager = new Backbone.Marionette.Region({
|
574
|
+
el: selector,
|
575
|
+
|
576
|
+
getEl: function(selector){
|
577
|
+
return that.$(selector);
|
578
|
+
}
|
579
|
+
});
|
580
|
+
that.regionManagers[name] = regionManager;
|
581
|
+
that[name] = regionManager;
|
582
|
+
});
|
583
|
+
},
|
584
|
+
|
585
|
+
// Close all of the regions that have been opened by
|
586
|
+
// this layout. This method is called when the layout
|
587
|
+
// itself is closed.
|
588
|
+
closeRegions: function () {
|
589
|
+
var that = this;
|
590
|
+
_.each(this.regionManagers, function (manager, name) {
|
591
|
+
manager.close();
|
592
|
+
delete that[name];
|
593
|
+
});
|
594
|
+
this.regionManagers = {};
|
595
|
+
}
|
596
|
+
});
|
597
|
+
|
598
|
+
// AppRouter
|
599
|
+
// ---------
|
600
|
+
|
601
|
+
// Reduce the boilerplate code of handling route events
|
602
|
+
// and then calling a single method on another object.
|
603
|
+
// Have your routers configured to call the method on
|
604
|
+
// your object, directly.
|
605
|
+
//
|
606
|
+
// Configure an AppRouter with `appRoutes`.
|
607
|
+
//
|
608
|
+
// App routers can only take one `controller` object.
|
609
|
+
// It is recommended that you divide your controller
|
610
|
+
// objects in to smaller peices of related functionality
|
611
|
+
// and have multiple routers / controllers, instead of
|
612
|
+
// just one giant router and controller.
|
613
|
+
//
|
614
|
+
// You can also add standard routes to an AppRouter.
|
615
|
+
|
616
|
+
Marionette.AppRouter = Backbone.Router.extend({
|
617
|
+
|
618
|
+
constructor: function(options){
|
619
|
+
Backbone.Router.prototype.constructor.call(this, options);
|
620
|
+
|
621
|
+
if (this.appRoutes){
|
622
|
+
var controller = this.controller;
|
623
|
+
if (options && options.controller) {
|
624
|
+
controller = options.controller;
|
625
|
+
}
|
626
|
+
this.processAppRoutes(controller, this.appRoutes);
|
627
|
+
}
|
628
|
+
},
|
629
|
+
|
630
|
+
processAppRoutes: function(controller, appRoutes){
|
631
|
+
var method, methodName;
|
632
|
+
var route, routesLength, i;
|
633
|
+
var routes = [];
|
634
|
+
var router = this;
|
635
|
+
|
636
|
+
for(route in appRoutes){
|
637
|
+
if (appRoutes.hasOwnProperty(route)){
|
638
|
+
routes.unshift([route, appRoutes[route]]);
|
639
|
+
}
|
640
|
+
}
|
641
|
+
|
642
|
+
routesLength = routes.length;
|
643
|
+
for (i = 0; i < routesLength; i++){
|
644
|
+
route = routes[i][0];
|
645
|
+
methodName = routes[i][1];
|
646
|
+
method = controller[methodName];
|
647
|
+
|
648
|
+
if (!method){
|
649
|
+
var msg = "Method '" + methodName + "' was not found on the controller";
|
650
|
+
var err = new Error(msg);
|
651
|
+
err.name = "NoMethodError";
|
652
|
+
throw err;
|
653
|
+
}
|
654
|
+
|
655
|
+
method = _.bind(method, controller);
|
656
|
+
router.route(route, methodName, method);
|
657
|
+
}
|
658
|
+
}
|
659
|
+
});
|
660
|
+
|
661
|
+
// Composite Application
|
662
|
+
// ---------------------
|
663
|
+
|
664
|
+
// Contain and manage the composite application as a whole.
|
665
|
+
// Stores and starts up `Region` objects, includes an
|
666
|
+
// event aggregator as `app.vent`
|
667
|
+
Marionette.Application = function(options){
|
668
|
+
this.initCallbacks = new Marionette.Callbacks();
|
669
|
+
this.vent = new Marionette.EventAggregator();
|
670
|
+
_.extend(this, options);
|
671
|
+
};
|
672
|
+
|
673
|
+
_.extend(Marionette.Application.prototype, Backbone.Events, {
|
674
|
+
// Add an initializer that is either run at when the `start`
|
675
|
+
// method is called, or run immediately if added after `start`
|
676
|
+
// has already been called.
|
677
|
+
addInitializer: function(initializer){
|
678
|
+
this.initCallbacks.add(initializer);
|
679
|
+
},
|
680
|
+
|
681
|
+
// kick off all of the application's processes.
|
682
|
+
// initializes all of the regions that have been added
|
683
|
+
// to the app, and runs all of the initializer functions
|
684
|
+
start: function(options){
|
685
|
+
this.trigger("initialize:before", options);
|
686
|
+
this.initCallbacks.run(this, options);
|
687
|
+
this.trigger("initialize:after", options);
|
688
|
+
|
689
|
+
this.trigger("start", options);
|
690
|
+
},
|
691
|
+
|
692
|
+
// Add regions to your app.
|
693
|
+
// Accepts a hash of named strings or Region objects
|
694
|
+
// addRegions({something: "#someRegion"})
|
695
|
+
// addRegions{{something: Region.extend({el: "#someRegion"}) });
|
696
|
+
addRegions: function(regions){
|
697
|
+
var regionValue, regionObj, region;
|
698
|
+
|
699
|
+
for(region in regions){
|
700
|
+
if (regions.hasOwnProperty(region)){
|
701
|
+
regionValue = regions[region];
|
702
|
+
|
703
|
+
if (typeof regionValue === "string"){
|
704
|
+
regionObj = new Marionette.Region({
|
705
|
+
el: regionValue
|
706
|
+
});
|
707
|
+
} else {
|
708
|
+
regionObj = new regionValue();
|
709
|
+
}
|
710
|
+
|
711
|
+
this[region] = regionObj;
|
712
|
+
}
|
713
|
+
}
|
714
|
+
}
|
715
|
+
});
|
716
|
+
|
717
|
+
// BindTo: Event Binding
|
718
|
+
// ---------------------
|
719
|
+
|
720
|
+
// BindTo facilitates the binding and unbinding of events
|
721
|
+
// from objects that extend `Backbone.Events`. It makes
|
722
|
+
// unbinding events, even with anonymous callback functions,
|
723
|
+
// easy.
|
724
|
+
//
|
725
|
+
// Thanks to Johnny Oshika for this code.
|
726
|
+
// http://stackoverflow.com/questions/7567404/backbone-js-repopulate-or-recreate-the-view/7607853#7607853
|
727
|
+
Marionette.BindTo = {
|
728
|
+
// Store the event binding in array so it can be unbound
|
729
|
+
// easily, at a later point in time.
|
730
|
+
bindTo: function (obj, eventName, callback, context) {
|
731
|
+
context = context || this;
|
732
|
+
obj.on(eventName, callback, context);
|
733
|
+
|
734
|
+
if (!this.bindings) { this.bindings = []; }
|
735
|
+
|
736
|
+
var binding = {
|
737
|
+
obj: obj,
|
738
|
+
eventName: eventName,
|
739
|
+
callback: callback,
|
740
|
+
context: context
|
741
|
+
}
|
742
|
+
|
743
|
+
this.bindings.push(binding);
|
744
|
+
|
745
|
+
return binding;
|
746
|
+
},
|
747
|
+
|
748
|
+
// Unbind from a single binding object. Binding objects are
|
749
|
+
// returned from the `bindTo` method call.
|
750
|
+
unbindFrom: function(binding){
|
751
|
+
binding.obj.off(binding.eventName, binding.callback);
|
752
|
+
this.bindings = _.reject(this.bindings, function(bind){return bind === binding});
|
753
|
+
},
|
754
|
+
|
755
|
+
// Unbind all of the events that we have stored.
|
756
|
+
unbindAll: function () {
|
757
|
+
var that = this;
|
758
|
+
|
759
|
+
// The `unbindFrom` call removes elements from the array
|
760
|
+
// while it is being iterated, so clone it first.
|
761
|
+
var bindings = _.map(this.bindings, _.identity);
|
762
|
+
_.each(bindings, function (binding, index) {
|
763
|
+
that.unbindFrom(binding);
|
764
|
+
});
|
765
|
+
}
|
766
|
+
};
|
767
|
+
|
768
|
+
// Callbacks
|
769
|
+
// ---------
|
770
|
+
|
771
|
+
// A simple way of managing a collection of callbacks
|
772
|
+
// and executing them at a later point in time, using jQuery's
|
773
|
+
// `Deferred` object.
|
774
|
+
Marionette.Callbacks = function(){
|
775
|
+
this.deferred = $.Deferred();
|
776
|
+
this.promise = this.deferred.promise();
|
777
|
+
};
|
778
|
+
|
779
|
+
_.extend(Marionette.Callbacks.prototype, {
|
780
|
+
|
781
|
+
// Add a callback to be executed. Callbacks added here are
|
782
|
+
// guaranteed to execute, even if they are added after the
|
783
|
+
// `run` method is called.
|
784
|
+
add: function(callback){
|
785
|
+
this.promise.done(function(context, options){
|
786
|
+
callback.call(context, options);
|
787
|
+
});
|
788
|
+
},
|
789
|
+
|
790
|
+
// Run all registered callbacks with the context specified.
|
791
|
+
// Additional callbacks can be added after this has been run
|
792
|
+
// and they will still be executed.
|
793
|
+
run: function(context, options){
|
794
|
+
this.deferred.resolve(context, options);
|
795
|
+
}
|
796
|
+
});
|
797
|
+
|
798
|
+
// Event Aggregator
|
799
|
+
// ----------------
|
800
|
+
|
801
|
+
// A pub-sub object that can be used to decouple various parts
|
802
|
+
// of an application through event-driven architecture.
|
803
|
+
Marionette.EventAggregator = function(options){
|
804
|
+
_.extend(this, options);
|
805
|
+
};
|
806
|
+
|
807
|
+
_.extend(Marionette.EventAggregator.prototype, Backbone.Events, Marionette.BindTo, {
|
808
|
+
// Assumes the event aggregator itself is the
|
809
|
+
// object being bound to.
|
810
|
+
bindTo: function(eventName, callback, context){
|
811
|
+
return Marionette.BindTo.bindTo.call(this, this, eventName, callback, context);
|
812
|
+
}
|
813
|
+
});
|
814
|
+
|
815
|
+
// Template Cache
|
816
|
+
// --------------
|
817
|
+
|
818
|
+
// Manage templates stored in `<script>` blocks,
|
819
|
+
// caching them for faster access.
|
820
|
+
Marionette.TemplateCache = {
|
821
|
+
templates: {},
|
822
|
+
loaders: {},
|
823
|
+
|
824
|
+
// Get the specified template by id. Either
|
825
|
+
// retrieves the cached version, or loads it
|
826
|
+
// from the DOM.
|
827
|
+
get: function(templateId){
|
828
|
+
var that = this;
|
829
|
+
var templateRetrieval = $.Deferred();
|
830
|
+
var cachedTemplate = this.templates[templateId];
|
831
|
+
|
832
|
+
if (cachedTemplate){
|
833
|
+
templateRetrieval.resolve(cachedTemplate);
|
834
|
+
} else {
|
835
|
+
var loader = this.loaders[templateId];
|
836
|
+
if(loader) {
|
837
|
+
templateRetrieval = loader;
|
838
|
+
} else {
|
839
|
+
this.loaders[templateId] = templateRetrieval;
|
840
|
+
|
841
|
+
this.loadTemplate(templateId, function(template){
|
842
|
+
delete that.loaders[templateId];
|
843
|
+
that.templates[templateId] = template;
|
844
|
+
templateRetrieval.resolve(template);
|
845
|
+
});
|
846
|
+
}
|
847
|
+
|
848
|
+
}
|
849
|
+
|
850
|
+
return templateRetrieval.promise();
|
851
|
+
},
|
852
|
+
|
853
|
+
// Load a template from the DOM, by default. Override
|
854
|
+
// this method to provide your own template retrieval,
|
855
|
+
// such as asynchronous loading from a server.
|
856
|
+
loadTemplate: function(templateId, callback){
|
857
|
+
var template = $(templateId).html();
|
858
|
+
|
859
|
+
// Make sure we have a template before trying to compile it
|
860
|
+
if (!template || template.length === 0){
|
861
|
+
var msg = "Could not find template: '" + templateId + "'";
|
862
|
+
var err = new Error(msg);
|
863
|
+
err.name = "NoTemplateError";
|
864
|
+
throw err;
|
865
|
+
}
|
866
|
+
|
867
|
+
template = this.compileTemplate(template);
|
868
|
+
|
869
|
+
callback.call(this, template);
|
870
|
+
},
|
871
|
+
|
872
|
+
// Pre-compile the template before caching it. Override
|
873
|
+
// this method if you do not need to pre-compile a template
|
874
|
+
// (JST / RequireJS for example) or if you want to change
|
875
|
+
// the template engine used (Handebars, etc).
|
876
|
+
compileTemplate: function(rawTemplate){
|
877
|
+
return _.template(rawTemplate);
|
878
|
+
},
|
879
|
+
|
880
|
+
// Clear templates from the cache. If no arguments
|
881
|
+
// are specified, clears all templates:
|
882
|
+
// `clear()`
|
883
|
+
//
|
884
|
+
// If arguments are specified, clears each of the
|
885
|
+
// specified templates from the cache:
|
886
|
+
// `clear("#t1", "#t2", "...")`
|
887
|
+
clear: function(){
|
888
|
+
var i;
|
889
|
+
var length = arguments.length;
|
890
|
+
|
891
|
+
if (length > 0){
|
892
|
+
for(i=0; i<length; i++){
|
893
|
+
delete this.templates[arguments[i]];
|
894
|
+
}
|
895
|
+
} else {
|
896
|
+
this.templates = {};
|
897
|
+
}
|
898
|
+
}
|
899
|
+
};
|
900
|
+
|
901
|
+
// Renderer
|
902
|
+
// --------
|
903
|
+
|
904
|
+
// Render a template with data by passing in the template
|
905
|
+
// selector and the data to render.
|
906
|
+
Marionette.Renderer = {
|
907
|
+
|
908
|
+
// Render a template with data. The `template` parameter is
|
909
|
+
// passed to the `TemplateCache` object to retrieve the
|
910
|
+
// actual template. Override this method to provide your own
|
911
|
+
// custom rendering and template handling for all of Marionette.
|
912
|
+
render: function(template, data){
|
913
|
+
var that = this;
|
914
|
+
var asyncRender = $.Deferred();
|
915
|
+
|
916
|
+
var templateRetrieval = Marionette.TemplateCache.get(template);
|
917
|
+
|
918
|
+
$.when(templateRetrieval).then(function(template){
|
919
|
+
var html = that.renderTemplate(template, data);
|
920
|
+
asyncRender.resolve(html);
|
921
|
+
});
|
922
|
+
|
923
|
+
return asyncRender.promise();
|
924
|
+
},
|
925
|
+
|
926
|
+
// Default implementation uses underscore.js templates. Override
|
927
|
+
// this method to use your own templating engine.
|
928
|
+
renderTemplate: function(template, data){
|
929
|
+
var html = template(data);
|
930
|
+
return html;
|
931
|
+
}
|
932
|
+
|
933
|
+
};
|
934
|
+
|
935
|
+
// Modules
|
936
|
+
// -------
|
937
|
+
|
938
|
+
// The "Modules" object builds modules on an
|
939
|
+
// object that it is attached to. It should not be
|
940
|
+
// used on it's own, but should be attached to
|
941
|
+
// another object that will define modules.
|
942
|
+
Marionette.Modules = {
|
943
|
+
|
944
|
+
// Add modules to the application, providing direct
|
945
|
+
// access to your applicaiton object, Backbone,
|
946
|
+
// Marionette, jQuery and Underscore as parameters
|
947
|
+
// to a callback function.
|
948
|
+
module: function(moduleNames, moduleDefinition){
|
949
|
+
var moduleName, module, moduleOverride;
|
950
|
+
var parentModule = this;
|
951
|
+
var parentApp = this;
|
952
|
+
var moduleNames = moduleNames.split(".");
|
953
|
+
|
954
|
+
// Loop through all the parts of the module definition
|
955
|
+
var length = moduleNames.length;
|
956
|
+
for(var i = 0; i < length; i++){
|
957
|
+
var isLastModuleInChain = (i === length-1);
|
958
|
+
|
959
|
+
// Get the module name, and check if it exists on
|
960
|
+
// the current parent already
|
961
|
+
moduleName = moduleNames[i];
|
962
|
+
module = parentModule[moduleName];
|
963
|
+
|
964
|
+
// Create a new module if we don't have one already
|
965
|
+
if (!module){
|
966
|
+
module = new Marionette.Application();
|
967
|
+
}
|
968
|
+
|
969
|
+
// Check to see if we need to run the definition
|
970
|
+
// for the module. Only run the definition if one
|
971
|
+
// is supplied, and if we're at the last segment
|
972
|
+
// of the "Module.Name" chain.
|
973
|
+
if (isLastModuleInChain && moduleDefinition){
|
974
|
+
moduleOverride = moduleDefinition(module, parentApp, Backbone, Marionette, jQuery, _);
|
975
|
+
// If we have a module override, use it instead.
|
976
|
+
if (moduleOverride){
|
977
|
+
module = moduleOverride;
|
978
|
+
}
|
979
|
+
}
|
980
|
+
|
981
|
+
// If the defined module is not what we are
|
982
|
+
// currently storing as the module, replace it
|
983
|
+
if (parentModule[moduleName] !== module){
|
984
|
+
parentModule[moduleName] = module;
|
985
|
+
}
|
986
|
+
|
987
|
+
// Reset the parent module so that the next child
|
988
|
+
// in the list will be added to the correct parent
|
989
|
+
parentModule = module;
|
990
|
+
}
|
991
|
+
|
992
|
+
// Return the last module in the definition chain
|
993
|
+
return module;
|
994
|
+
}
|
995
|
+
};
|
996
|
+
|
997
|
+
// Helpers
|
998
|
+
// -------
|
999
|
+
|
1000
|
+
// For slicing `arguments` in functions
|
1001
|
+
var slice = Array.prototype.slice;
|
1002
|
+
|
1003
|
+
// Copy the `extend` function used by Backbone's classes
|
1004
|
+
var extend = Marionette.View.extend;
|
1005
|
+
Marionette.Region.extend = extend;
|
1006
|
+
Marionette.Application.extend = extend;
|
1007
|
+
|
1008
|
+
// Copy the `modules` feature on to the `Application` object
|
1009
|
+
Marionette.Application.prototype.module = Marionette.Modules.module;
|
1010
|
+
|
1011
|
+
// Copy the features of `BindTo` on to these objects
|
1012
|
+
_.extend(Marionette.View.prototype, Marionette.BindTo);
|
1013
|
+
_.extend(Marionette.Application.prototype, Marionette.BindTo);
|
1014
|
+
_.extend(Marionette.Region.prototype, Marionette.BindTo);
|
1015
|
+
|
1016
|
+
// A simple wrapper method for deferring a callback until
|
1017
|
+
// after another method has been called, passing the
|
1018
|
+
// results of the first method to the second. Uses jQuery's
|
1019
|
+
// deferred / promise objects, and $.when/then to make it
|
1020
|
+
// work.
|
1021
|
+
var callDeferredMethod = function(fn, callback, context){
|
1022
|
+
var promise;
|
1023
|
+
if (fn) { promise = fn.call(context); }
|
1024
|
+
$.when(promise).then(callback);
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
|
1028
|
+
return Marionette;
|
1029
|
+
})(Backbone, _, window.jQuery || window.Zepto || window.ender);
|
1030
|
+
|
1031
|
+
return Backbone.Marionette;
|
1032
|
+
|
1033
|
+
}));
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: marionette-amd-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Godfrey Chan
|
9
|
+
- Andrey Subbotin
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-06-04 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rails
|
17
|
+
requirement: &70171054207440 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.1.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70171054207440
|
26
|
+
description: Vendors AMD Backbone.Marionette for use with asset pipeline.
|
27
|
+
email:
|
28
|
+
- godfreykfc@gmail.com
|
29
|
+
- andrey@subbotin.me
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- lib/marionette-rails.rb
|
35
|
+
- vendor/assets/javascripts/backbone.marionette.js
|
36
|
+
- LICENSE
|
37
|
+
- README.md
|
38
|
+
homepage: https://github.com/eploko/marionette-amd-rails
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.3.6
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.8.10
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: AMD Backbone.Marionette for Rails
|
62
|
+
test_files: []
|