| 
									
										
										
										
											2015-04-30 13:38:40 -07:00
										 |  |  | import {Directive} from 'angular2/src/core/annotations_impl/annotations'; | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  | import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref'; | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  | import {ViewRef, ProtoViewRef} from 'angular2/src/core/compiler/view_ref'; | 
					
						
							| 
									
										
										
										
											2015-02-05 13:08:05 -08:00
										 |  |  | import {isPresent, isBlank} from 'angular2/src/facade/lang'; | 
					
						
							|  |  |  | import {ListWrapper} from 'angular2/src/facade/collection'; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-31 22:47:11 +00:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2015-04-06 11:47:38 +02:00
										 |  |  |  * The `For` directive instantiates a template once per item from an iterable. The context for each | 
					
						
							|  |  |  |  * instantiated template inherits from the outer context with the given loop variable set to the | 
					
						
							|  |  |  |  * current item from the iterable. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * It is possible to alias the `index` to a local variable that will be set to the current loop | 
					
						
							|  |  |  |  * iteration in the template context. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When the contents of the iterator changes, `For` makes the corresponding changes to the DOM: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * * When an item is added, a new instance of the template is added to the DOM. | 
					
						
							|  |  |  |  * * When an item is removed, its template instance is removed from the DOM. | 
					
						
							|  |  |  |  * * When items are reordered, their respective templates are reordered in the DOM. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * # Example | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * <ul> | 
					
						
							| 
									
										
										
										
											2015-04-28 12:11:34 +02:00
										 |  |  |  *   <li *for="#error of errors; #i = index"> | 
					
						
							| 
									
										
										
										
											2015-04-06 11:47:38 +02:00
										 |  |  |  *     Error {{i}} of {{errors.length}}: {{error.message}} | 
					
						
							|  |  |  |  *   </li> | 
					
						
							|  |  |  |  * </ul> | 
					
						
							|  |  |  |  * ```
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * # Syntax | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - `<li *for="#item of items; #i = index">...</li>` | 
					
						
							|  |  |  |  * - `<li template="for #item of items; #i=index">...</li>` | 
					
						
							|  |  |  |  * - `<template [for]="#item" [of]="items" #i="index"><li>...</li></template>` | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-04-10 12:45:02 +02:00
										 |  |  |  * @exportedAs angular2/directives | 
					
						
							| 
									
										
										
										
											2015-03-31 22:47:11 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-04-30 13:38:40 -07:00
										 |  |  | @Directive({ | 
					
						
							| 
									
										
										
										
											2015-03-13 16:22:01 -07:00
										 |  |  |   selector: '[for][of]', | 
					
						
							| 
									
										
										
										
											2015-04-09 21:20:11 +02:00
										 |  |  |   properties: { | 
					
						
							| 
									
										
										
										
											2015-03-13 16:22:01 -07:00
										 |  |  |     'iterableChanges': 'of | iterableDiff' | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2015-03-13 16:22:01 -07:00
										 |  |  | export class For  { | 
					
						
							| 
									
										
										
										
											2015-04-27 09:26:55 -07:00
										 |  |  |   viewContainer: ViewContainerRef; | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |   protoViewRef: ProtoViewRef; | 
					
						
							|  |  |  |   constructor(viewContainer:ViewContainerRef, protoViewRef: ProtoViewRef) { | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |     this.viewContainer = viewContainer; | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |     this.protoViewRef = protoViewRef; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-12 14:56:41 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   set iterableChanges(changes) { | 
					
						
							|  |  |  |     if (isBlank(changes)) { | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |       this.viewContainer.clear(); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // TODO(rado): check if change detection can produce a change record that is
 | 
					
						
							|  |  |  |     // easier to consume than current.
 | 
					
						
							|  |  |  |     var recordViewTuples = []; | 
					
						
							| 
									
										
										
										
											2015-02-12 14:56:41 -08:00
										 |  |  |     changes.forEachRemovedItem( | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       (removedRecord) => ListWrapper.push(recordViewTuples, new RecordViewTuple(removedRecord, null)) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-12 14:56:41 -08:00
										 |  |  |     changes.forEachMovedItem( | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       (movedRecord) => ListWrapper.push(recordViewTuples, new RecordViewTuple(movedRecord, null)) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 16:22:01 -07:00
										 |  |  |     var insertTuples = For.bulkRemove(recordViewTuples, this.viewContainer); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-12 14:56:41 -08:00
										 |  |  |     changes.forEachAddedItem( | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       (addedRecord) => ListWrapper.push(insertTuples, new RecordViewTuple(addedRecord, null)) | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |     For.bulkInsert(insertTuples, this.viewContainer, this.protoViewRef); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (var i = 0; i < insertTuples.length; i++) { | 
					
						
							|  |  |  |       this.perViewChange(insertTuples[i].view, insertTuples[i].record); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   perViewChange(view, record) { | 
					
						
							| 
									
										
										
										
											2015-01-27 22:34:25 -08:00
										 |  |  |     view.setLocal('\$implicit', record.item); | 
					
						
							| 
									
										
										
										
											2015-01-28 00:42:08 +01:00
										 |  |  |     view.setLocal('index', record.currentIndex); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |   static bulkRemove(tuples, viewContainer) { | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     tuples.sort((a, b) => a.record.previousIndex - b.record.previousIndex); | 
					
						
							|  |  |  |     var movedTuples = []; | 
					
						
							|  |  |  |     for (var i = tuples.length - 1; i >= 0; i--) { | 
					
						
							|  |  |  |       var tuple = tuples[i]; | 
					
						
							| 
									
										
										
										
											2015-01-15 13:03:50 -08:00
										 |  |  |       // separate moved views from removed views.
 | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       if (isPresent(tuple.record.currentIndex)) { | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |         tuple.view = viewContainer.detach(tuple.record.previousIndex); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |         ListWrapper.push(movedTuples, tuple); | 
					
						
							| 
									
										
										
										
											2015-01-15 13:03:50 -08:00
										 |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |         viewContainer.remove(tuple.record.previousIndex); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return movedTuples; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |   static bulkInsert(tuples, viewContainer, protoViewRef) { | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |     tuples.sort((a, b) => a.record.currentIndex - b.record.currentIndex); | 
					
						
							|  |  |  |     for (var i = 0; i < tuples.length; i++) { | 
					
						
							|  |  |  |       var tuple = tuples[i]; | 
					
						
							|  |  |  |       if (isPresent(tuple.view)) { | 
					
						
							| 
									
										
										
										
											2015-02-12 11:54:22 +01:00
										 |  |  |         viewContainer.insert(tuple.view, tuple.record.currentIndex); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2015-04-29 15:07:55 -07:00
										 |  |  |         tuple.view = viewContainer.create(protoViewRef, tuple.record.currentIndex); | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return tuples; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RecordViewTuple { | 
					
						
							| 
									
										
										
										
											2015-04-28 11:20:01 -07:00
										 |  |  |   view: ViewRef; | 
					
						
							| 
									
										
										
										
											2014-12-05 17:44:00 -08:00
										 |  |  |   record: any; | 
					
						
							|  |  |  |   constructor(record, view) { | 
					
						
							|  |  |  |     this.record = record; | 
					
						
							|  |  |  |     this.view = view; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |