1
1
// MarionetteJS (Backbone.Marionette)
2
2
// ----------------------------------
3
- // v1.2.3
3
+ // v1.3.0
4
4
//
5
5
// Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
6
6
// Distributed under MIT license
@@ -576,8 +576,8 @@ Marionette.MonitorDOMRefresh = (function(){
576
576
// Marionette.bindEntityEvents & unbindEntityEvents
577
577
// ---------------------------
578
578
//
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.
581
581
//
582
582
// The first parameter, `target`, must have a `listenTo` method from the
583
583
// EventBinder object.
@@ -587,7 +587,7 @@ Marionette.MonitorDOMRefresh = (function(){
587
587
//
588
588
// The third parameter is a hash of { "event:name": "eventHandler" }
589
589
// 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.
591
591
592
592
( function ( Marionette ) {
593
593
"use strict" ;
@@ -629,7 +629,7 @@ Marionette.MonitorDOMRefresh = (function(){
629
629
target . stopListening ( entity , evt , method , target ) ;
630
630
}
631
631
632
-
632
+
633
633
// generic looping function
634
634
function iterateEvents ( target , entity , bindings , functionCallback , stringCallback ) {
635
635
if ( ! entity || ! bindings ) { return ; }
@@ -642,7 +642,7 @@ Marionette.MonitorDOMRefresh = (function(){
642
642
// iterate the bindings and bind them
643
643
_ . each ( bindings , function ( methods , evt ) {
644
644
645
- // allow for a function as the handler,
645
+ // allow for a function as the handler,
646
646
// or a list of event names as a string
647
647
if ( _ . isFunction ( methods ) ) {
648
648
functionCallback ( target , entity , evt , methods ) ;
@@ -652,7 +652,7 @@ Marionette.MonitorDOMRefresh = (function(){
652
652
653
653
} ) ;
654
654
}
655
-
655
+
656
656
// Export Public API
657
657
Marionette . bindEntityEvents = function ( target , entity , bindings ) {
658
658
iterateEvents ( target , entity , bindings , bindToFunction , bindFromStrings ) ;
@@ -679,7 +679,7 @@ Marionette.Callbacks = function(){
679
679
_ . extend ( Marionette . Callbacks . prototype , {
680
680
681
681
// 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
683
683
// `run` method is called.
684
684
add : function ( callback , contextOverride ) {
685
685
this . _callbacks . push ( { cb : callback , ctx : contextOverride } ) ;
@@ -690,8 +690,8 @@ _.extend(Marionette.Callbacks.prototype, {
690
690
} ) ;
691
691
} ,
692
692
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
695
695
// and they will still be executed.
696
696
run : function ( options , context ) {
697
697
this . _deferred . resolve ( context , options ) ;
@@ -703,7 +703,7 @@ _.extend(Marionette.Callbacks.prototype, {
703
703
var callbacks = this . _callbacks ;
704
704
this . _deferred = Marionette . $ . Deferred ( ) ;
705
705
this . _callbacks = [ ] ;
706
-
706
+
707
707
_ . each ( callbacks , function ( cb ) {
708
708
this . add ( cb . cb , cb . ctx ) ;
709
709
} , this ) ;
@@ -740,7 +740,7 @@ _.extend(Marionette.Controller.prototype, Backbone.Events, {
740
740
}
741
741
} ) ;
742
742
743
- // Region
743
+ // Region
744
744
// ------
745
745
//
746
746
// Manage the visual regions of your composite application. See
@@ -795,19 +795,19 @@ _.extend(Marionette.Region, {
795
795
}
796
796
797
797
var selector , RegionType ;
798
-
798
+
799
799
// get the selector for the region
800
-
800
+
801
801
if ( regionIsString ) {
802
802
selector = regionConfig ;
803
- }
803
+ }
804
804
805
805
if ( regionConfig . selector ) {
806
806
selector = regionConfig . selector ;
807
807
}
808
808
809
809
// get the type for the region
810
-
810
+
811
811
if ( regionIsType ) {
812
812
RegionType = regionConfig ;
813
813
}
@@ -819,7 +819,7 @@ _.extend(Marionette.Region, {
819
819
if ( regionConfig . regionType ) {
820
820
RegionType = regionConfig . regionType ;
821
821
}
822
-
822
+
823
823
// build the region instance
824
824
var region = new RegionType ( {
825
825
el : selector
@@ -874,7 +874,7 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
874
874
if ( isDifferentView || isViewClosed ) {
875
875
this . open ( view ) ;
876
876
}
877
-
877
+
878
878
this . currentView = view ;
879
879
880
880
Marionette . triggerMethod . call ( this , "show" , view ) ;
@@ -914,8 +914,8 @@ _.extend(Marionette.Region.prototype, Backbone.Events, {
914
914
delete this . currentView ;
915
915
} ,
916
916
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,
919
919
// and will not replace the current HTML for the `el`
920
920
// of the region.
921
921
attachView : function ( view ) {
@@ -1398,8 +1398,8 @@ Marionette.View = Backbone.View.extend({
1398
1398
// with underscore.js templates, serializing the view's model or collection,
1399
1399
// and calling several methods on extended views, such as `onRender`.
1400
1400
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
1403
1403
// Marionette.View.prototype.constructor which allows overriding
1404
1404
constructor : function ( ) {
1405
1405
Marionette . View . prototype . constructor . apply ( this , slice ( arguments ) ) ;
@@ -1480,6 +1480,25 @@ Marionette.CollectionView = Marionette.View.extend({
1480
1480
Marionette . View . prototype . constructor . apply ( this , slice ( arguments ) ) ;
1481
1481
1482
1482
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 ;
1483
1502
} ,
1484
1503
1485
1504
// Configured the initial events that the collection view
@@ -1538,6 +1557,8 @@ Marionette.CollectionView = Marionette.View.extend({
1538
1557
// more control over events being triggered, around the rendering
1539
1558
// process
1540
1559
_renderChildren : function ( ) {
1560
+ this . startBuffering ( ) ;
1561
+
1541
1562
this . closeEmptyView ( ) ;
1542
1563
this . closeChildren ( ) ;
1543
1564
@@ -1546,6 +1567,8 @@ Marionette.CollectionView = Marionette.View.extend({
1546
1567
} else {
1547
1568
this . showEmptyView ( ) ;
1548
1569
}
1570
+
1571
+ this . endBuffering ( ) ;
1549
1572
} ,
1550
1573
1551
1574
// Internal method to loop through each item in the
@@ -1608,9 +1631,9 @@ Marionette.CollectionView = Marionette.View.extend({
1608
1631
itemViewOptions = itemViewOptions . call ( this , item , index ) ;
1609
1632
}
1610
1633
1611
- // build the view
1634
+ // build the view
1612
1635
var view = this . buildItemView ( item , ItemView , itemViewOptions ) ;
1613
-
1636
+
1614
1637
// set up the child view event forwarding
1615
1638
this . addChildViewEventForwarding ( view ) ;
1616
1639
@@ -1696,11 +1719,26 @@ Marionette.CollectionView = Marionette.View.extend({
1696
1719
}
1697
1720
} ,
1698
1721
1722
+ // You might need to override this if you've overridden appendHtml
1723
+ appendBuffer : function ( collectionView , buffer ) {
1724
+ collectionView . $el . append ( buffer ) ;
1725
+ } ,
1726
+
1699
1727
// Append the HTML to the collection's `el`.
1700
1728
// Override this method to do something other
1701
1729
// then `.append`.
1702
1730
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
+ }
1704
1742
} ,
1705
1743
1706
1744
// Internal method to set up the `children` object for
@@ -1833,15 +1871,30 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
1833
1871
return Marionette . Renderer . render ( template , data ) ;
1834
1872
} ,
1835
1873
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
+
1836
1881
// Appends the `el` of itemView instances to the specified
1837
1882
// `itemViewContainer` (a jQuery selector). Override this method to
1838
1883
// provide custom logic of how the child item view instances have their
1839
1884
// 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
+ }
1843
1895
} ,
1844
1896
1897
+
1845
1898
// Internal method to ensure an `$itemViewContainer` exists, for the
1846
1899
// `appendHtml` method to use.
1847
1900
getItemViewContainer : function ( containerView ) {
@@ -1887,15 +1940,15 @@ Marionette.CompositeView = Marionette.CollectionView.extend({
1887
1940
// Used for composite view management and sub-application areas.
1888
1941
Marionette . Layout = Marionette . ItemView . extend ( {
1889
1942
regionType : Marionette . Region ,
1890
-
1943
+
1891
1944
// Ensure the regions are available when the `initialize` method
1892
1945
// is called.
1893
1946
constructor : function ( options ) {
1894
1947
options = options || { } ;
1895
1948
1896
1949
this . _firstRender = true ;
1897
1950
this . _initializeRegions ( options ) ;
1898
-
1951
+
1899
1952
Marionette . ItemView . prototype . constructor . call ( this , options ) ;
1900
1953
} ,
1901
1954
@@ -1906,7 +1959,7 @@ Marionette.Layout = Marionette.ItemView.extend({
1906
1959
render : function ( ) {
1907
1960
1908
1961
if ( this . isClosed ) {
1909
- // a previously closed layout means we need to
1962
+ // a previously closed layout means we need to
1910
1963
// completely re-initialize the regions
1911
1964
this . _initializeRegions ( ) ;
1912
1965
}
@@ -1915,7 +1968,7 @@ Marionette.Layout = Marionette.ItemView.extend({
1915
1968
// reset the regions
1916
1969
this . _firstRender = false ;
1917
1970
} 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
1919
1972
// re-initializing the `el` for each region
1920
1973
this . _reInitializeRegions ( ) ;
1921
1974
}
@@ -1966,7 +2019,7 @@ Marionette.Layout = Marionette.ItemView.extend({
1966
2019
} ,
1967
2020
1968
2021
// Internal method to initialize the regions that have been defined in a
1969
- // `regions` attribute on this layout.
2022
+ // `regions` attribute on this layout.
1970
2023
_initializeRegions : function ( options ) {
1971
2024
var regions ;
1972
2025
this . _initRegionManager ( ) ;
@@ -2123,7 +2176,7 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
2123
2176
this . triggerMethod ( "start" , options ) ;
2124
2177
} ,
2125
2178
2126
- // Add regions to your app.
2179
+ // Add regions to your app.
2127
2180
// Accepts a hash of named strings or Region objects
2128
2181
// addRegions({something: "#someRegion"})
2129
2182
// addRegions({something: Region.extend({el: "#someRegion"}) });
@@ -2142,7 +2195,7 @@ _.extend(Marionette.Application.prototype, Backbone.Events, {
2142
2195
removeRegion : function ( region ) {
2143
2196
this . _regionManager . removeRegion ( region ) ;
2144
2197
} ,
2145
-
2198
+
2146
2199
// Provides alternative access to regions
2147
2200
// Accepts the region name
2148
2201
// getRegion('main')
@@ -2340,7 +2393,7 @@ _.extend(Marionette.Module, {
2340
2393
} ,
2341
2394
2342
2395
_addModuleDefinition : function ( parentModule , module , def , args ) {
2343
- var fn ;
2396
+ var fn ;
2344
2397
var startWithParent ;
2345
2398
2346
2399
if ( _ . isFunction ( def ) ) {
@@ -2352,7 +2405,7 @@ _.extend(Marionette.Module, {
2352
2405
// if an object is supplied
2353
2406
fn = def . define ;
2354
2407
startWithParent = def . startWithParent ;
2355
-
2408
+
2356
2409
} else {
2357
2410
// if nothing is supplied
2358
2411
startWithParent = true ;
0 commit comments