PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/angular2/es6/prod/src/upgrade/upgrade_ng1_adapter.js

https://gitlab.com/remynaps/Vexillarius
JavaScript | 286 lines | 284 code | 0 blank | 2 comment | 64 complexity | f6b41f3a1f57212482c694294b7d1b61 MD5 | raw file
  1. import { Directive, ElementRef, EventEmitter, Inject } from 'angular2/core';
  2. import { NG1_COMPILE, NG1_SCOPE, NG1_HTTP_BACKEND, NG1_TEMPLATE_CACHE, NG1_CONTROLLER } from './constants';
  3. import { controllerKey } from './util';
  4. import * as angular from './angular_js';
  5. const CAMEL_CASE = /([A-Z])/g;
  6. const INITIAL_VALUE = {
  7. __UNINITIALIZED__: true
  8. };
  9. const NOT_SUPPORTED = 'NOT_SUPPORTED';
  10. export class UpgradeNg1ComponentAdapterBuilder {
  11. constructor(name) {
  12. this.name = name;
  13. this.inputs = [];
  14. this.inputsRename = [];
  15. this.outputs = [];
  16. this.outputsRename = [];
  17. this.propertyOutputs = [];
  18. this.checkProperties = [];
  19. this.propertyMap = {};
  20. this.linkFn = null;
  21. this.directive = null;
  22. this.$controller = null;
  23. var selector = name.replace(CAMEL_CASE, (all, next) => '-' + next.toLowerCase());
  24. var self = this;
  25. this.type =
  26. Directive({ selector: selector, inputs: this.inputsRename, outputs: this.outputsRename })
  27. .Class({
  28. constructor: [
  29. new Inject(NG1_SCOPE),
  30. ElementRef,
  31. function (scope, elementRef) {
  32. return new UpgradeNg1ComponentAdapter(self.linkFn, scope, self.directive, elementRef, self.$controller, self.inputs, self.outputs, self.propertyOutputs, self.checkProperties, self.propertyMap);
  33. }
  34. ],
  35. ngOnInit: function () { },
  36. ngOnChanges: function () { },
  37. ngDoCheck: function () { }
  38. });
  39. }
  40. extractDirective(injector) {
  41. var directives = injector.get(this.name + 'Directive');
  42. if (directives.length > 1) {
  43. throw new Error('Only support single directive definition for: ' + this.name);
  44. }
  45. var directive = directives[0];
  46. if (directive.replace)
  47. this.notSupported('replace');
  48. if (directive.terminal)
  49. this.notSupported('terminal');
  50. var link = directive.link;
  51. if (typeof link == 'object') {
  52. if (link.post)
  53. this.notSupported('link.post');
  54. }
  55. return directive;
  56. }
  57. notSupported(feature) {
  58. throw new Error(`Upgraded directive '${this.name}' does not support '${feature}'.`);
  59. }
  60. extractBindings() {
  61. var btcIsObject = typeof this.directive.bindToController === 'object';
  62. if (btcIsObject && Object.keys(this.directive.scope).length) {
  63. throw new Error(`Binding definitions on scope and controller at the same time are not supported.`);
  64. }
  65. var context = (btcIsObject) ? this.directive.bindToController : this.directive.scope;
  66. if (typeof context == 'object') {
  67. for (var name in context) {
  68. if (context.hasOwnProperty(name)) {
  69. var localName = context[name];
  70. var type = localName.charAt(0);
  71. localName = localName.substr(1) || name;
  72. var outputName = 'output_' + name;
  73. var outputNameRename = outputName + ': ' + name;
  74. var outputNameRenameChange = outputName + ': ' + name + 'Change';
  75. var inputName = 'input_' + name;
  76. var inputNameRename = inputName + ': ' + name;
  77. switch (type) {
  78. case '=':
  79. this.propertyOutputs.push(outputName);
  80. this.checkProperties.push(localName);
  81. this.outputs.push(outputName);
  82. this.outputsRename.push(outputNameRenameChange);
  83. this.propertyMap[outputName] = localName;
  84. // don't break; let it fall through to '@'
  85. case '@':
  86. // handle the '<' binding of angular 1.5 components
  87. case '<':
  88. this.inputs.push(inputName);
  89. this.inputsRename.push(inputNameRename);
  90. this.propertyMap[inputName] = localName;
  91. break;
  92. case '&':
  93. this.outputs.push(outputName);
  94. this.outputsRename.push(outputNameRename);
  95. this.propertyMap[outputName] = localName;
  96. break;
  97. default:
  98. var json = JSON.stringify(context);
  99. throw new Error(`Unexpected mapping '${type}' in '${json}' in '${this.name}' directive.`);
  100. }
  101. }
  102. }
  103. }
  104. }
  105. compileTemplate(compile, templateCache, httpBackend) {
  106. if (this.directive.template !== undefined) {
  107. this.linkFn = compileHtml(this.directive.template);
  108. }
  109. else if (this.directive.templateUrl) {
  110. var url = this.directive.templateUrl;
  111. var html = templateCache.get(url);
  112. if (html !== undefined) {
  113. this.linkFn = compileHtml(html);
  114. }
  115. else {
  116. return new Promise((resolve, err) => {
  117. httpBackend('GET', url, null, (status, response) => {
  118. if (status == 200) {
  119. resolve(this.linkFn = compileHtml(templateCache.put(url, response)));
  120. }
  121. else {
  122. err(`GET ${url} returned ${status}: ${response}`);
  123. }
  124. });
  125. });
  126. }
  127. }
  128. else {
  129. throw new Error(`Directive '${this.name}' is not a component, it is missing template.`);
  130. }
  131. return null;
  132. function compileHtml(html) {
  133. var div = document.createElement('div');
  134. div.innerHTML = html;
  135. return compile(div.childNodes);
  136. }
  137. }
  138. static resolve(exportedComponents, injector) {
  139. var promises = [];
  140. var compile = injector.get(NG1_COMPILE);
  141. var templateCache = injector.get(NG1_TEMPLATE_CACHE);
  142. var httpBackend = injector.get(NG1_HTTP_BACKEND);
  143. var $controller = injector.get(NG1_CONTROLLER);
  144. for (var name in exportedComponents) {
  145. if (exportedComponents.hasOwnProperty(name)) {
  146. var exportedComponent = exportedComponents[name];
  147. exportedComponent.directive = exportedComponent.extractDirective(injector);
  148. exportedComponent.$controller = $controller;
  149. exportedComponent.extractBindings();
  150. var promise = exportedComponent.compileTemplate(compile, templateCache, httpBackend);
  151. if (promise)
  152. promises.push(promise);
  153. }
  154. }
  155. return Promise.all(promises);
  156. }
  157. }
  158. class UpgradeNg1ComponentAdapter {
  159. constructor(linkFn, scope, directive, elementRef, $controller, inputs, outputs, propOuts, checkProperties, propertyMap) {
  160. this.directive = directive;
  161. this.inputs = inputs;
  162. this.outputs = outputs;
  163. this.propOuts = propOuts;
  164. this.checkProperties = checkProperties;
  165. this.propertyMap = propertyMap;
  166. this.destinationObj = null;
  167. this.checkLastValues = [];
  168. var element = elementRef.nativeElement;
  169. var childNodes = [];
  170. var childNode;
  171. while (childNode = element.firstChild) {
  172. element.removeChild(childNode);
  173. childNodes.push(childNode);
  174. }
  175. var componentScope = scope.$new(!!directive.scope);
  176. var $element = angular.element(element);
  177. var controllerType = directive.controller;
  178. var controller = null;
  179. if (controllerType) {
  180. var locals = { $scope: componentScope, $element: $element };
  181. controller = $controller(controllerType, locals, null, directive.controllerAs);
  182. $element.data(controllerKey(directive.name), controller);
  183. }
  184. var link = directive.link;
  185. if (typeof link == 'object')
  186. link = link.pre;
  187. if (link) {
  188. var attrs = NOT_SUPPORTED;
  189. var transcludeFn = NOT_SUPPORTED;
  190. var linkController = this.resolveRequired($element, directive.require);
  191. directive.link(componentScope, $element, attrs, linkController, transcludeFn);
  192. }
  193. this.destinationObj = directive.bindToController && controller ? controller : componentScope;
  194. linkFn(componentScope, (clonedElement, scope) => {
  195. for (var i = 0, ii = clonedElement.length; i < ii; i++) {
  196. element.appendChild(clonedElement[i]);
  197. }
  198. }, { parentBoundTranscludeFn: (scope, cloneAttach) => { cloneAttach(childNodes); } });
  199. for (var i = 0; i < inputs.length; i++) {
  200. this[inputs[i]] = null;
  201. }
  202. for (var j = 0; j < outputs.length; j++) {
  203. var emitter = this[outputs[j]] = new EventEmitter();
  204. this.setComponentProperty(outputs[j], ((emitter) => (value) => emitter.emit(value))(emitter));
  205. }
  206. for (var k = 0; k < propOuts.length; k++) {
  207. this[propOuts[k]] = new EventEmitter();
  208. this.checkLastValues.push(INITIAL_VALUE);
  209. }
  210. }
  211. ngOnInit() {
  212. if (this.destinationObj.$onInit) {
  213. this.destinationObj.$onInit();
  214. }
  215. }
  216. ngOnChanges(changes) {
  217. for (var name in changes) {
  218. if (changes.hasOwnProperty(name)) {
  219. var change = changes[name];
  220. this.setComponentProperty(name, change.currentValue);
  221. }
  222. }
  223. }
  224. ngDoCheck() {
  225. var count = 0;
  226. var destinationObj = this.destinationObj;
  227. var lastValues = this.checkLastValues;
  228. var checkProperties = this.checkProperties;
  229. for (var i = 0; i < checkProperties.length; i++) {
  230. var value = destinationObj[checkProperties[i]];
  231. var last = lastValues[i];
  232. if (value !== last) {
  233. if (typeof value == 'number' && isNaN(value) && typeof last == 'number' && isNaN(last)) {
  234. }
  235. else {
  236. var eventEmitter = this[this.propOuts[i]];
  237. eventEmitter.emit(lastValues[i] = value);
  238. }
  239. }
  240. }
  241. return count;
  242. }
  243. setComponentProperty(name, value) {
  244. this.destinationObj[this.propertyMap[name]] = value;
  245. }
  246. resolveRequired($element, require) {
  247. if (!require) {
  248. return undefined;
  249. }
  250. else if (typeof require == 'string') {
  251. var name = require;
  252. var isOptional = false;
  253. var startParent = false;
  254. var searchParents = false;
  255. var ch;
  256. if (name.charAt(0) == '?') {
  257. isOptional = true;
  258. name = name.substr(1);
  259. }
  260. if (name.charAt(0) == '^') {
  261. searchParents = true;
  262. name = name.substr(1);
  263. }
  264. if (name.charAt(0) == '^') {
  265. startParent = true;
  266. name = name.substr(1);
  267. }
  268. var key = controllerKey(name);
  269. if (startParent)
  270. $element = $element.parent();
  271. var dep = searchParents ? $element.inheritedData(key) : $element.data(key);
  272. if (!dep && !isOptional) {
  273. throw new Error(`Can not locate '${require}' in '${this.directive.name}'.`);
  274. }
  275. return dep;
  276. }
  277. else if (require instanceof Array) {
  278. var deps = [];
  279. for (var i = 0; i < require.length; i++) {
  280. deps.push(this.resolveRequired($element, require[i]));
  281. }
  282. return deps;
  283. }
  284. throw new Error(`Directive '${this.directive.name}' require syntax unrecognized: ${this.directive.require}`);
  285. }
  286. }