// A view that iterates over a Backbone.Collection// and renders an individual ItemView for each model.Marionette.FasterCollectionView= Marionette.View.extend({// used as the prefix for item view events// that are forwarded through the collectionview itemViewEventPrefix:"itemview",// constructor constructor:function(options){this._initChildViewStorage();

Marionette.View.prototype.constructor.apply(this, slice(arguments));

this._initialEvents();this.initRenderBuffer();},

// Instead of inserting elements one by one into the page,// it's much more performant to insert elements into a document// fragment and then insert that document fragment into the page initRenderBuffer:function(){this.elBuffer= document.createDocumentFragment();},

// Configured the initial events that the collection view// binds to. Override this method to prevent the initial// events, or to add your own initial events. _initialEvents:function(){if(this.collection){this.listenTo(this.collection,"add",this.addChildView,this);this.listenTo(this.collection,"remove",this.removeItemView,this);this.listenTo(this.collection,"reset",this.render,this);}},

// Internal method to close an existing emptyView instance// if one exists. Called when a collection view has been// rendered empty, and then an item is added to the collection. closeEmptyView:function(){if(this._showingEmptyView){this.closeChildren();deletethis._showingEmptyView;}},

// Retrieve the itemView type, either from `this.options.itemView`// or from the `itemView` in the object definition. The "options"// takes precedence. getItemView:function(item){var itemView = Marionette.getOption(this,"itemView");

if(!itemView){ throwError("An `itemView` must be specified","NoItemViewError");}

return itemView;},

// Render the child item's view and add it to the// HTML for the collection view. addItemView:function(item, ItemView, index){// get the itemViewOptions if any were specifiedvar itemViewOptions = Marionette.getOption(this,"itemViewOptions");if(_.isFunction(itemViewOptions)){ itemViewOptions = itemViewOptions.call(this,item, index);}

// get the child view by item it holds, and remove it removeItemView:function(item){var view =this.children.findByModel(item);this.removeChildView(view);this.checkEmpty();},

// Remove the child view and close it removeChildView:function(view){// shut down the child view properly,// including events that the collection has from itif(view){this.stopListening(view);

// call 'close' or 'remove', depending on which is foundif(view.close){ view.close();}elseif(view.remove){ view.remove();}

this.children.remove(view);}

this.triggerMethod("item:removed", view);},

// helper to show the empty view if the collection is empty checkEmpty:function(){// check if we're empty now, and if we are, show the// empty viewif(!this.collection||this.collection.length===0){this.showEmptyView();}},

// Append the HTML to the collection's `el`.// Override this method to do something other// then `.append`. appendHtml:function(collectionView, itemView, index){if(collectionView.isBuffering){ collectionView.elBuffer.appendChild(itemView.el);}else{// If we've already rendered the main collection, just// append the new items directly into the element. collectionView.$el.append(itemView.el);}},

// Internal method to set up the `children` object for// storing all of the child views _initChildViewStorage:function(){this.children=new Backbone.ChildViewContainer();},

// Handle cleanup and other closing needs for// the collection of views.close:function(){if(this.isClosed){return;}