docs: function()
  	{
  		var boundView, i, l, el, a;
  		var lastView, lastChild, parentNode, item;
  		var insertBefore = defaultInsertBefore;
  		var removeChild = defaultRemoveChild;
  		var oldCollection = this.collection;
  
  		if(this.animate)
  		{
  			insertBefore = this.view.scope[this.animate]['insert'];
  			removeChild = this.view.scope[this.animate]['remove'];
  		}
  
  		this.rebindCollection();
  
  		// This will speed up rendering but requires strictly immutable collections
  		if(settings.immutableCollections && oldCollection === this.collection) return;
  
  		if(this.boundViews === null) this.boundViews = [];
  
  		if(this.boundViews.length === 0)
  		{
  			// Fast initial rendering:
  			l = this.collection.length;
  			if(l > 0)
  			{
  				a = this.collection;
  				lastChild = this.anchor;
  				if(this.anchor && this.anchor.parentNode)
  				{
  					parentNode = this.anchor.parentNode;
  					for(i = 0; i < l; i++)
  					{
  						boundView = this.createBoundView(a[i]);
  						this.boundViews[i].runAll();
  						this.boundViews[i].afterRunAll();
  						el = boundView.element;
  						insertBefore(parentNode, lastChild.nextSibling, el);
  						lastChild = el;
  					}
  				}
  			}
  		}
  		else
  		{
  			// Diff based rendering:
  			var newCollection = this.collection;
  			var newBoundViews = [];
  			var recycledViews = [];
  			var oldCollectionKeyMap;
  			var newCollectionKeyMap;
  			if(this.keyProp)
  			{
  				oldCollectionKeyMap = {};
  				for(i = 0, l = oldCollection.length; i < l; i++)
  				{
  					oldCollectionKeyMap[oldCollection[i][this.keyProp]] = i;
  				}
  
  				newCollectionKeyMap = {};
  				for(i = 0, l = newCollection.length; i < l; i++)
  				{
  					newCollectionKeyMap[newCollection[i][this.keyProp]] = i;
  				}
  			}
  
  			// Merge old and new bound view arrays:
  			var tempBoundViews = [];
  			for(i = 0, l = Math.max(oldCollection.length, newCollection.length); i < l; i++)
  			{
  				if(oldCollection[i] && getKeyedItemIndex(newCollection, oldCollection[i], this.keyProp, newCollectionKeyMap) === -1)
  				{
  					// Item is in the old collection but not in the new one
  					boundView = this.boundViews[i];
  					if(this.animate)
  					{
  						tempBoundViews.push(boundView);
  						lastView = boundView;
  					}
  					else lastView = null;
  					recycledViews.push(boundView);
  				}
  				if(newCollection[i])
  				{
  					// Item is in the new collection
  					var oldIndex = getKeyedItemIndex(oldCollection, newCollection[i], this.keyProp, oldCollectionKeyMap);
  					if(oldIndex !== -1)
  					{
  						// Item is already rendered, reuse its view
  						boundView = this.boundViews[oldIndex];
  						tempBoundViews.push(boundView);
  						boundView.scope['*'] = this.cursor.refine([i]);
  						if(this.view._itemAlias) boundView.scope[this.view._itemAlias] = boundView.scope['*'];
  						boundView.setBindingIndex(i);
  						newBoundViews.push(boundView);
  						lastView = boundView;
  					}
  					else
  					{
  						// Item is new, create new binding view
  						if(this.animate || recycledViews.length === 0)
  						{
  							boundView = this.createBoundView(newCollection[i]);
  							boundView.scope['*'] = this.cursor.refine([i]);
  							if(this.view._itemAlias) boundView.scope[this.view._itemAlias] = boundView.scope['*'];
  							boundView.setBindingIndex(i);
  							boundView.runAll();
  							boundView.afterRunAll();
  						}
  						else
  						{
  							boundView = recycledViews.shift();
  							boundView.scope['*'] = this.cursor.refine([i]);
  							if(this.view._itemAlias) boundView.scope[this.view._itemAlias] = boundView.scope['*'];
  							boundView.setBindingIndex(i);
  						}
  						tempBoundViews.push(boundView);
  						newBoundViews.push(boundView);
  						lastView = null;
  					}
  				}
  			}
  
  			if(lastView)
  			{
  				// Reordering elements from the last one:
  				lastChild = lastView.element;
  				i = tempBoundViews.length - 1;
  
  				el = tempBoundViews[i].element;
  				if(el !== lastChild && lastChild.parentNode && lastChild.parentNode.nodeType === 1 && el !== lastChild.nextSibling)
  				{
  					insertBefore(lastChild.parentNode, lastChild.nextSibling, el);
  					lastChild = el;
  				}
  
  				for(; i >= 0; i--)
  				{
  					el = tempBoundViews[i].element;
  					var nextSibling = el.nextSibling;
  					if(el !== lastChild && nextSibling !== lastChild && lastChild.parentNode && lastChild.parentNode.nodeType === 1)
  					{
  						insertBefore(lastChild.parentNode, lastChild, el);
  					}
  					lastChild = el;
  					tempBoundViews[i].refreshIndexedBinders(true);
  				}
  			}
  			else
  			{
  				// Add elements after anchor text node:
  				lastChild = this.anchor;
  				if(this.anchor.parentNode)
  				{
  					parentNode = this.anchor.parentNode;
  				}
  				for(i = 0, l = tempBoundViews.length; i < l; i++)
  				{
  					el = tempBoundViews[i].element;
  
  					if(el !== lastChild.nextSibling)
  					{
  						insertBefore(parentNode, lastChild.nextSibling, el);
  					}
  					tempBoundViews[i].refreshIndexedBinders(true);
  					lastChild = el;
  				}
  			}
  			this.boundViews = newBoundViews;
  
  			// Remove old views:
  			for(i = 0, l = recycledViews.length; i < l; i++)
  			{
  				var viewToRemove = recycledViews[i];
  				if(viewToRemove.element && viewToRemove.element.parentNode)
  				{
  					removeNodeAsync(viewToRemove, removeChild);
  				}
  			}
  		}
  	}