| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | import { | 
					
						
							|  |  |  |   bind, | 
					
						
							| 
									
										
										
										
											2015-10-10 22:11:13 -07:00
										 |  |  |   provide, | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   AppViewManager, | 
					
						
							|  |  |  |   ChangeDetectorRef, | 
					
						
							|  |  |  |   HostViewRef, | 
					
						
							|  |  |  |   Injector, | 
					
						
							|  |  |  |   ProtoViewRef, | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |   SimpleChange | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | } from 'angular2/angular2'; | 
					
						
							|  |  |  | import {NG1_SCOPE} from './constants'; | 
					
						
							|  |  |  | import {ComponentInfo} from './metadata'; | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  | import Element = protractor.Element; | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  | import * as angular from './angular_js'; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | const INITIAL_VALUE = { | 
					
						
							|  |  |  |   __UNINITIALIZED__: true | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-12 21:32:41 -07:00
										 |  |  | export class DowngradeNg2ComponentAdapter { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   component: any = null; | 
					
						
							|  |  |  |   inputChangeCount: number = 0; | 
					
						
							|  |  |  |   inputChanges: {[key: string]: SimpleChange} = null; | 
					
						
							|  |  |  |   hostViewRef: HostViewRef = null; | 
					
						
							|  |  |  |   changeDetector: ChangeDetectorRef = null; | 
					
						
							|  |  |  |   componentScope: angular.IScope; | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |   childNodes: Node[]; | 
					
						
							|  |  |  |   contentInserctionPoint: Node = null; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   constructor(private id: string, private info: ComponentInfo, | 
					
						
							|  |  |  |               private element: angular.IAugmentedJQuery, private attrs: angular.IAttributes, | 
					
						
							|  |  |  |               private scope: angular.IScope, private parentInjector: Injector, | 
					
						
							|  |  |  |               private parse: angular.IParseService, private viewManager: AppViewManager, | 
					
						
							|  |  |  |               private protoView: ProtoViewRef) { | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |     (<any>this.element[0]).id = id; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     this.componentScope = scope.$new(); | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |     this.childNodes = <Node[]><any>element.contents(); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bootstrapNg2() { | 
					
						
							| 
									
										
										
										
											2015-10-10 22:11:13 -07:00
										 |  |  |     var childInjector = this.parentInjector.resolveAndCreateChild( | 
					
						
							| 
									
										
										
										
											2015-10-12 11:30:34 -07:00
										 |  |  |         [provide(NG1_SCOPE, {useValue: this.componentScope})]); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     this.hostViewRef = | 
					
						
							|  |  |  |         this.viewManager.createRootHostView(this.protoView, '#' + this.id, childInjector); | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |     var renderer: any = (<any>this.hostViewRef).render; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     var hostElement = this.viewManager.getHostElement(this.hostViewRef); | 
					
						
							|  |  |  |     this.changeDetector = this.hostViewRef.changeDetectorRef; | 
					
						
							|  |  |  |     this.component = this.viewManager.getComponent(hostElement); | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |     this.contentInserctionPoint = renderer.rootContentInsertionPoints[0]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |   setupInputs(): void { | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |     var attrs = this.attrs; | 
					
						
							|  |  |  |     var inputs = this.info.inputs; | 
					
						
							|  |  |  |     for (var i = 0; i < inputs.length; i++) { | 
					
						
							|  |  |  |       var input = inputs[i]; | 
					
						
							|  |  |  |       var expr = null; | 
					
						
							|  |  |  |       if (attrs.hasOwnProperty(input.attr)) { | 
					
						
							|  |  |  |         var observeFn = ((prop) => { | 
					
						
							|  |  |  |           var prevValue = INITIAL_VALUE; | 
					
						
							|  |  |  |           return (value) => { | 
					
						
							|  |  |  |             if (this.inputChanges !== null) { | 
					
						
							|  |  |  |               this.inputChangeCount++; | 
					
						
							|  |  |  |               this.inputChanges[prop] = | 
					
						
							|  |  |  |                   new Ng1Change(value, prevValue === INITIAL_VALUE ? value : prevValue); | 
					
						
							|  |  |  |               prevValue = value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             this.component[prop] = value; | 
					
						
							| 
									
										
										
										
											2015-10-26 20:17:46 -07:00
										 |  |  |           }; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         })(input.prop); | 
					
						
							|  |  |  |         attrs.$observe(input.attr, observeFn); | 
					
						
							|  |  |  |       } else if (attrs.hasOwnProperty(input.bindAttr)) { | 
					
						
							|  |  |  |         expr = attrs[input.bindAttr]; | 
					
						
							|  |  |  |       } else if (attrs.hasOwnProperty(input.bracketAttr)) { | 
					
						
							|  |  |  |         expr = attrs[input.bracketAttr]; | 
					
						
							|  |  |  |       } else if (attrs.hasOwnProperty(input.bindonAttr)) { | 
					
						
							|  |  |  |         expr = attrs[input.bindonAttr]; | 
					
						
							|  |  |  |       } else if (attrs.hasOwnProperty(input.bracketParenAttr)) { | 
					
						
							|  |  |  |         expr = attrs[input.bracketParenAttr]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (expr != null) { | 
					
						
							|  |  |  |         var watchFn = ((prop) => (value, prevValue) => { | 
					
						
							|  |  |  |           if (this.inputChanges != null) { | 
					
						
							|  |  |  |             this.inputChangeCount++; | 
					
						
							|  |  |  |             this.inputChanges[prop] = new Ng1Change(prevValue, value); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           this.component[prop] = value; | 
					
						
							|  |  |  |         })(input.prop); | 
					
						
							|  |  |  |         this.componentScope.$watch(expr, watchFn); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     var prototype = this.info.type.prototype; | 
					
						
							|  |  |  |     if (prototype && prototype.onChanges) { | 
					
						
							|  |  |  |       // Detect: OnChanges interface
 | 
					
						
							|  |  |  |       this.inputChanges = {}; | 
					
						
							|  |  |  |       this.componentScope.$watch(() => this.inputChangeCount, () => { | 
					
						
							|  |  |  |         var inputChanges = this.inputChanges; | 
					
						
							|  |  |  |         this.inputChanges = {}; | 
					
						
							|  |  |  |         this.component.onChanges(inputChanges); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-10-11 11:18:11 -07:00
										 |  |  |     this.componentScope.$watch(() => this.changeDetector && this.changeDetector.detectChanges()); | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-09 14:53:04 -07:00
										 |  |  |   projectContent() { | 
					
						
							|  |  |  |     var childNodes = this.childNodes; | 
					
						
							|  |  |  |     if (this.contentInserctionPoint) { | 
					
						
							|  |  |  |       var parent = this.contentInserctionPoint.parentNode; | 
					
						
							|  |  |  |       for (var i = 0, ii = childNodes.length; i < ii; i++) { | 
					
						
							|  |  |  |         parent.insertBefore(childNodes[i], this.contentInserctionPoint); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |   setupOutputs() { | 
					
						
							|  |  |  |     var attrs = this.attrs; | 
					
						
							|  |  |  |     var outputs = this.info.outputs; | 
					
						
							|  |  |  |     for (var j = 0; j < outputs.length; j++) { | 
					
						
							|  |  |  |       var output = outputs[j]; | 
					
						
							|  |  |  |       var expr = null; | 
					
						
							|  |  |  |       var assignExpr = false; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       var bindonAttr = | 
					
						
							|  |  |  |           output.bindonAttr ? output.bindonAttr.substring(0, output.bindonAttr.length - 6) : null; | 
					
						
							|  |  |  |       var bracketParenAttr = | 
					
						
							|  |  |  |           output.bracketParenAttr ? | 
					
						
							|  |  |  |               `[(${output.bracketParenAttr.substring(2, output.bracketParenAttr.length - 8)})]` : | 
					
						
							|  |  |  |               null; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |       if (attrs.hasOwnProperty(output.onAttr)) { | 
					
						
							|  |  |  |         expr = attrs[output.onAttr]; | 
					
						
							|  |  |  |       } else if (attrs.hasOwnProperty(output.parenAttr)) { | 
					
						
							|  |  |  |         expr = attrs[output.parenAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(bindonAttr)) { | 
					
						
							|  |  |  |         expr = attrs[bindonAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         assignExpr = true; | 
					
						
							| 
									
										
										
										
											2015-10-10 19:56:22 -07:00
										 |  |  |       } else if (attrs.hasOwnProperty(bracketParenAttr)) { | 
					
						
							|  |  |  |         expr = attrs[bracketParenAttr]; | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |         assignExpr = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (expr != null && assignExpr != null) { | 
					
						
							|  |  |  |         var getter = this.parse(expr); | 
					
						
							|  |  |  |         var setter = getter.assign; | 
					
						
							|  |  |  |         if (assignExpr && !setter) { | 
					
						
							|  |  |  |           throw new Error(`Expression '${expr}' is not assignable!`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         var emitter = this.component[output.prop]; | 
					
						
							|  |  |  |         if (emitter) { | 
					
						
							| 
									
										
										
										
											2015-10-24 18:48:43 -07:00
										 |  |  |           emitter.subscribe({ | 
					
						
							| 
									
										
										
										
											2015-10-04 09:33:20 -07:00
										 |  |  |             next: assignExpr ? ((setter) => (value) => setter(this.scope, value))(setter) : | 
					
						
							|  |  |  |                                ((getter) => (value) => getter(this.scope, {$event: value}))(getter) | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           throw new Error(`Missing emitter '${output.prop}' on component '${this.info.selector}'!`); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   registerCleanup() { | 
					
						
							|  |  |  |     this.element.bind('$remove', () => this.viewManager.destroyRootHostView(this.hostViewRef)); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Ng1Change implements SimpleChange { | 
					
						
							|  |  |  |   constructor(public previousValue: any, public currentValue: any) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   isFirstChange(): boolean { return this.previousValue === this.currentValue; } | 
					
						
							|  |  |  | } |