Skip to content

Commit 66268eb

Browse files
committed
bump and build v1.3.0
1 parent 3116913 commit 66268eb

37 files changed

+686
-361
lines changed

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description" : "Make your Backbone.js apps dance with a composite application architecture!",
44
"url" : "http://marionettejs.org",
55
"main" : "./lib/backbone.marionette.js",
6-
"version" : "1.2.3",
6+
"version" : "1.3.0",
77

88
"keywords" : [
99
"backbone",

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### v1.3.0 [view commit logs](https://github.com/marionettejs/backbone.marionette/compare/v1.2.3...v1.3.0)
2+
* CompositeView / CollectionView
3+
* Massive perf boost in rendering collection and composite views by using document fragments [jsPerf](http://jsperf.com/marionette-documentfragment-collectionview/5)
4+
15
### v1.2.3 [view commit logs](https://github.com/marionettejs/backbone.marionette/compare/v1.2.2...v1.2.3)
26
* CompositeView
37
* Fixed bug where ```child views``` were being added before the initial render, thus raising errors.

lib/backbone.marionette.js

Lines changed: 90 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MarionetteJS (Backbone.Marionette)
22
// ----------------------------------
3-
// v1.2.3
3+
// v1.3.0
44
//
55
// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
66
// Distributed under MIT license
@@ -576,8 +576,8 @@ Marionette.MonitorDOMRefresh = (function(){
576576
// Marionette.bindEntityEvents & unbindEntityEvents
577577
// ---------------------------
578578
//
579-
// These methods are used to bind/unbind a backbone "entity" (collection/model)
580-
// to methods on a target object.
579+
// These methods are used to bind/unbind a backbone "entity" (collection/model)
580+
// to methods on a target object.
581581
//
582582
// The first parameter, `target`, must have a `listenTo` method from the
583583
// EventBinder object.
@@ -587,7 +587,7 @@ Marionette.MonitorDOMRefresh = (function(){
587587
//
588588
// The third parameter is a hash of { "event:name": "eventHandler" }
589589
// configuration. Multiple handlers can be separated by a space. A
590-
// function can be supplied instead of a string handler name.
590+
// function can be supplied instead of a string handler name.
591591

592592
(function(Marionette){
593593
"use strict";
@@ -629,7 +629,7 @@ Marionette.MonitorDOMRefresh = (function(){
629629
target.stopListening(entity, evt, method, target);
630630
}
631631

632-
632+
633633
// generic looping function
634634
function iterateEvents(target, entity, bindings, functionCallback, stringCallback){
635635
if (!entity || !bindings) { return; }
@@ -642,7 +642,7 @@ Marionette.MonitorDOMRefresh = (function(){
642642
// iterate the bindings and bind them
643643
_.each(bindings, function(methods, evt){
644644

645-
// allow for a function as the handler,
645+
// allow for a function as the handler,
646646
// or a list of event names as a string
647647
if (_.isFunction(methods)){
648648
functionCallback(target, entity, evt, methods);
@@ -652,7 +652,7 @@ Marionette.MonitorDOMRefresh = (function(){
652652

653653
});
654654
}
655-
655+
656656
// Export Public API
657657
Marionette.bindEntityEvents = function(target, entity, bindings){
658658
iterateEvents(target, entity, bindings, bindToFunction, bindFromStrings);
@@ -679,7 +679,7 @@ Marionette.Callbacks = function(){
679679
_.extend(Marionette.Callbacks.prototype, {
680680

681681
// Add a callback to be executed. Callbacks added here are
682-
// guaranteed to execute, even if they are added after the
682+
// guaranteed to execute, even if they are added after the
683683
// `run` method is called.
684684
add: function(callback, contextOverride){
685685
this._callbacks.push({cb: callback, ctx: contextOverride});
@@ -690,8 +690,8 @@ _.extend(Marionette.Callbacks.prototype, {
690690
});
691691
},
692692

693-
// Run all registered callbacks with the context specified.
694-
// Additional callbacks can be added after this has been run
693+
// Run all registered callbacks with the context specified.
694+
// Additional callbacks can be added after this has been run
695695
// and they will still be executed.
696696
run: function(options, context){
697697
this._deferred.resolve(context, options);
@@ -703,7 +703,7 @@ _.extend(Marionette.Callbacks.prototype, {
703703
var callbacks = this._callbacks;
704704
this._deferred = Marionette.$.Deferred();
705705
this._callbacks = [];
706-
706+
707707
_.each(callbacks, function(cb){
708708
this.add(cb.cb, cb.ctx);
709709
}, this);
@@ -740,7 +740,7 @@ _.extend(Marionette.Controller.prototype, Backbone.Events, {
740740
}
741741
});
742742

743-
// Region
743+
// Region
744744
// ------
745745
//
746746
// Manage the visual regions of your composite application. See
@@ -795,19 +795,19 @@ _.extend(Marionette.Region, {
795795
}
796796

797797
var selector, RegionType;
798-
798+
799799
// get the selector for the region
800-
800+
801801
if (regionIsString) {
802802
selector = regionConfig;
803-
}
803+
}
804804

805805
if (regionConfig.selector) {
806806
selector = regionConfig.selector;
807807
}
808808

809809
// get the type for the region
810-
810+
811811
if (regionIsType){
812812
RegionType = regionConfig;
813813
}
@@ -819,7 +819,7 @@ _.extend(Marionette.Region, {
819819
if (regionConfig.regionType) {
820820
RegionType = regionConfig.regionType;
821821
}
822-
822+
823823
// build the region instance
824824
var region = new RegionType({
825825
el: selector
@@ -874,7 +874,7 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
874874
if (isDifferentView || isViewClosed) {
875875
this.open(view);
876876
}
877-
877+
878878
this.currentView = view;
879879

880880
Marionette.triggerMethod.call(this, "show", view);
@@ -914,8 +914,8 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
914914
delete this.currentView;
915915
},
916916

917-
// Attach an existing view to the region. This
918-
// will not call `render` or `onShow` for the new view,
917+
// Attach an existing view to the region. This
918+
// will not call `render` or `onShow` for the new view,
919919
// and will not replace the current HTML for the `el`
920920
// of the region.
921921
attachView: function(view){
@@ -1398,8 +1398,8 @@ Marionette.View = Backbone.View.extend({
13981398
// with underscore.js templates, serializing the view's model or collection,
13991399
// and calling several methods on extended views, such as `onRender`.
14001400
Marionette.ItemView = Marionette.View.extend({
1401-
1402-
// Setting up the inheritance chain which allows changes to
1401+
1402+
// Setting up the inheritance chain which allows changes to
14031403
// Marionette.View.prototype.constructor which allows overriding
14041404
constructor: function(){
14051405
Marionette.View.prototype.constructor.apply(this, slice(arguments));
@@ -1480,6 +1480,25 @@ Marionette.CollectionView = Marionette.View.extend({
14801480
Marionette.View.prototype.constructor.apply(this, slice(arguments));
14811481

14821482
this._initialEvents();
1483+
this.initRenderBuffer();
1484+
},
1485+
1486+
// Instead of inserting elements one by one into the page,
1487+
// it's much more performant to insert elements into a document
1488+
// fragment and then insert that document fragment into the page
1489+
initRenderBuffer: function() {
1490+
this.elBuffer = document.createDocumentFragment();
1491+
},
1492+
1493+
startBuffering: function() {
1494+
this.initRenderBuffer();
1495+
this.isBuffering = true;
1496+
},
1497+
1498+
endBuffering: function() {
1499+
this.appendBuffer(this, this.elBuffer);
1500+
this.initRenderBuffer();
1501+
this.isBuffering = false;
14831502
},
14841503

14851504
// Configured the initial events that the collection view
@@ -1538,6 +1557,8 @@ Marionette.CollectionView = Marionette.View.extend({
15381557
// more control over events being triggered, around the rendering
15391558
// process
15401559
_renderChildren: function(){
1560+
this.startBuffering();
1561+
15411562
this.closeEmptyView();
15421563
this.closeChildren();
15431564

@@ -1546,6 +1567,8 @@ Marionette.CollectionView = Marionette.View.extend({
15461567
} else {
15471568
this.showEmptyView();
15481569
}
1570+
1571+
this.endBuffering();
15491572
},
15501573

15511574
// Internal method to loop through each item in the
@@ -1608,9 +1631,9 @@ Marionette.CollectionView = Marionette.View.extend({
16081631
itemViewOptions = itemViewOptions.call(this, item, index);
16091632
}
16101633

1611-
// build the view
1634+
// build the view
16121635
var view = this.buildItemView(item, ItemView, itemViewOptions);
1613-
1636+
16141637
// set up the child view event forwarding
16151638
this.addChildViewEventForwarding(view);
16161639

@@ -1696,11 +1719,26 @@ Marionette.CollectionView = Marionette.View.extend({
16961719
}
16971720
},
16981721

1722+
// You might need to override this if you've overridden appendHtml
1723+
appendBuffer: function(collectionView, buffer) {
1724+
collectionView.$el.append(buffer);
1725+
},
1726+
16991727
// Append the HTML to the collection's `el`.
17001728
// Override this method to do something other
17011729
// then `.append`.
17021730
appendHtml: function(collectionView, itemView, index){
1703-
collectionView.$el.append(itemView.el);
1731+
if (collectionView.isBuffering) {
1732+
// buffering happens on reset events and initial renders
1733+
// in order to reduce the number of inserts into the
1734+
// document, which are expensive.
1735+
collectionView.elBuffer.appendChild(itemView.el);
1736+
}
1737+
else {
1738+
// If we've already rendered the main collection, just
1739+
// append the new items directly into the element.
1740+
collectionView.$el.append(itemView.el);
1741+
}
17041742
},
17051743

17061744
// Internal method to set up the `children` object for
@@ -1833,15 +1871,30 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
18331871
return Marionette.Renderer.render(template, data);
18341872
},
18351873

1874+
1875+
// You might need to override this if you've overridden appendHtml
1876+
appendBuffer: function(compositeView, buffer) {
1877+
var $container = this.getItemViewContainer(compositeView);
1878+
$container.append(buffer);
1879+
},
1880+
18361881
// Appends the `el` of itemView instances to the specified
18371882
// `itemViewContainer` (a jQuery selector). Override this method to
18381883
// provide custom logic of how the child item view instances have their
18391884
// HTML appended to the composite view instance.
1840-
appendHtml: function(cv, iv, index){
1841-
var $container = this.getItemViewContainer(cv);
1842-
$container.append(iv.el);
1885+
appendHtml: function(compositeView, itemView, index){
1886+
if (compositeView.isBuffering) {
1887+
compositeView.elBuffer.appendChild(itemView.el);
1888+
}
1889+
else {
1890+
// If we've already rendered the main collection, just
1891+
// append the new items directly into the element.
1892+
var $container = this.getItemViewContainer(compositeView);
1893+
$container.append(itemView.el);
1894+
}
18431895
},
18441896

1897+
18451898
// Internal method to ensure an `$itemViewContainer` exists, for the
18461899
// `appendHtml` method to use.
18471900
getItemViewContainer: function(containerView){
@@ -1887,15 +1940,15 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
18871940
// Used for composite view management and sub-application areas.
18881941
Marionette.Layout = Marionette.ItemView.extend({
18891942
regionType: Marionette.Region,
1890-
1943+
18911944
// Ensure the regions are available when the `initialize` method
18921945
// is called.
18931946
constructor: function (options) {
18941947
options = options || {};
18951948

18961949
this._firstRender = true;
18971950
this._initializeRegions(options);
1898-
1951+
18991952
Marionette.ItemView.prototype.constructor.call(this, options);
19001953
},
19011954

@@ -1906,7 +1959,7 @@ Marionette.Layout = Marionette.ItemView.extend({
19061959
render: function(){
19071960

19081961
if (this.isClosed){
1909-
// a previously closed layout means we need to
1962+
// a previously closed layout means we need to
19101963
// completely re-initialize the regions
19111964
this._initializeRegions();
19121965
}
@@ -1915,7 +1968,7 @@ Marionette.Layout = Marionette.ItemView.extend({
19151968
// reset the regions
19161969
this._firstRender = false;
19171970
} else if (!this.isClosed){
1918-
// If this is not the first render call, then we need to
1971+
// If this is not the first render call, then we need to
19191972
// re-initializing the `el` for each region
19201973
this._reInitializeRegions();
19211974
}
@@ -1966,7 +2019,7 @@ Marionette.Layout = Marionette.ItemView.extend({
19662019
},
19672020

19682021
// Internal method to initialize the regions that have been defined in a
1969-
// `regions` attribute on this layout.
2022+
// `regions` attribute on this layout.
19702023
_initializeRegions: function (options) {
19712024
var regions;
19722025
this._initRegionManager();
@@ -2123,7 +2176,7 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
21232176
this.triggerMethod("start", options);
21242177
},
21252178

2126-
// Add regions to your app.
2179+
// Add regions to your app.
21272180
// Accepts a hash of named strings or Region objects
21282181
// addRegions({something: "#someRegion"})
21292182
// addRegions({something: Region.extend({el: "#someRegion"}) });
@@ -2142,7 +2195,7 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
21422195
removeRegion: function(region) {
21432196
this._regionManager.removeRegion(region);
21442197
},
2145-
2198+
21462199
// Provides alternative access to regions
21472200
// Accepts the region name
21482201
// getRegion('main')
@@ -2340,7 +2393,7 @@ _.extend(Marionette.Module, {
23402393
},
23412394

23422395
_addModuleDefinition: function(parentModule, module, def, args){
2343-
var fn;
2396+
var fn;
23442397
var startWithParent;
23452398

23462399
if (_.isFunction(def)){
@@ -2352,7 +2405,7 @@ _.extend(Marionette.Module, {
23522405
// if an object is supplied
23532406
fn = def.define;
23542407
startWithParent = def.startWithParent;
2355-
2408+
23562409
} else {
23572410
// if nothing is supplied
23582411
startWithParent = true;

lib/backbone.marionette.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/backbone.marionette.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)