| Index: third_party/pkg/angular/lib/core_dom/shadow_dom_component_factory.dart
|
| diff --git a/third_party/pkg/angular/lib/core_dom/shadow_dom_component_factory.dart b/third_party/pkg/angular/lib/core_dom/shadow_dom_component_factory.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8cfe4132ee93c8c603eae5a7e2c3cae8e42fc3e1
|
| --- /dev/null
|
| +++ b/third_party/pkg/angular/lib/core_dom/shadow_dom_component_factory.dart
|
| @@ -0,0 +1,146 @@
|
| +part of angular.core.dom_internal;
|
| +
|
| +abstract class ComponentFactory {
|
| + FactoryFn call(dom.Node node, DirectiveRef ref);
|
| +
|
| + static async.Future<ViewFactory> _viewFuture(
|
| + Component component, ViewCache viewCache, DirectiveMap directives) {
|
| + if (component.template != null) {
|
| + return new async.Future.value(viewCache.fromHtml(component.template, directives));
|
| + }
|
| + if (component.templateUrl != null) {
|
| + return viewCache.fromUrl(component.templateUrl, directives);
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + static TemplateLoader _setupOnShadowDomAttach(controller, templateLoader, shadowScope) {
|
| + if (controller is ShadowRootAware) {
|
| + templateLoader.template.then((shadowDom) {
|
| + if (!shadowScope.isAttached) return;
|
| + (controller as ShadowRootAware).onShadowRoot(shadowDom);
|
| + });
|
| + }
|
| + }
|
| +}
|
| +
|
| +class ShadowDomComponentFactory implements ComponentFactory {
|
| + final Expando _expando;
|
| +
|
| + ShadowDomComponentFactory(this._expando);
|
| +
|
| + FactoryFn call(dom.Node node, DirectiveRef ref) {
|
| + return (Injector injector) {
|
| + var component = ref.annotation as Component;
|
| + Scope scope = injector.get(Scope);
|
| + ViewCache viewCache = injector.get(ViewCache);
|
| + Http http = injector.get(Http);
|
| + TemplateCache templateCache = injector.get(TemplateCache);
|
| + DirectiveMap directives = injector.get(DirectiveMap);
|
| + NgBaseCss baseCss = injector.get(NgBaseCss);
|
| + // This is a bit of a hack since we are returning different type then we are.
|
| + var componentFactory = new _ComponentFactory(node, ref.type, component,
|
| + injector.get(dom.NodeTreeSanitizer), _expando, baseCss);
|
| + var controller = componentFactory.call(injector, scope, viewCache, http, templateCache,
|
| + directives);
|
| +
|
| + componentFactory.shadowScope.context[component.publishAs] = controller;
|
| + return controller;
|
| + };
|
| + }
|
| +}
|
| +
|
| +
|
| +/**
|
| + * ComponentFactory is responsible for setting up components. This includes
|
| + * the shadowDom, fetching template, importing styles, setting up attribute
|
| + * mappings, publishing the controller, and compiling and caching the template.
|
| + */
|
| +class _ComponentFactory implements Function {
|
| +
|
| + final dom.Element element;
|
| + final Type type;
|
| + final Component component;
|
| + final dom.NodeTreeSanitizer treeSanitizer;
|
| + final Expando _expando;
|
| + final NgBaseCss _baseCss;
|
| +
|
| + dom.ShadowRoot shadowDom;
|
| + Scope shadowScope;
|
| + Injector shadowInjector;
|
| + var controller;
|
| +
|
| + _ComponentFactory(this.element, this.type, this.component, this.treeSanitizer,
|
| + this._expando, this._baseCss);
|
| +
|
| + dynamic call(Injector injector, Scope scope,
|
| + ViewCache viewCache, Http http, TemplateCache templateCache,
|
| + DirectiveMap directives) {
|
| + shadowDom = element.createShadowRoot()
|
| + ..applyAuthorStyles = component.applyAuthorStyles
|
| + ..resetStyleInheritance = component.resetStyleInheritance;
|
| +
|
| + shadowScope = scope.createChild({}); // Isolate
|
| + // TODO(pavelgj): fetching CSS with Http is mainly an attempt to
|
| + // work around an unfiled Chrome bug when reloading same CSS breaks
|
| + // styles all over the page. We shouldn't be doing browsers work,
|
| + // so change back to using @import once Chrome bug is fixed or a
|
| + // better work around is found.
|
| + List<async.Future<String>> cssFutures = new List();
|
| + var cssUrls = []..addAll(_baseCss.urls)..addAll(component.cssUrls);
|
| + if (cssUrls.isNotEmpty) {
|
| + cssUrls.forEach((css) => cssFutures.add(http
|
| + .get(css, cache: templateCache).then(
|
| + (resp) => resp.responseText,
|
| + onError: (e) => '/*\n$e\n*/\n')
|
| + ));
|
| + } else {
|
| + cssFutures.add(new async.Future.value(null));
|
| + }
|
| + var viewFuture = ComponentFactory._viewFuture(component, viewCache, directives);
|
| + TemplateLoader templateLoader = new TemplateLoader(
|
| + async.Future.wait(cssFutures).then((Iterable<String> cssList) {
|
| + if (cssList != null) {
|
| + shadowDom.setInnerHtml(
|
| + cssList
|
| + .where((css) => css != null)
|
| + .map((css) => '<style>$css</style>')
|
| + .join(''),
|
| + treeSanitizer: treeSanitizer);
|
| + }
|
| + if (viewFuture != null) {
|
| + return viewFuture.then((ViewFactory viewFactory) {
|
| + return (!shadowScope.isAttached) ?
|
| + shadowDom :
|
| + attachViewToShadowDom(viewFactory);
|
| + });
|
| + }
|
| + return shadowDom;
|
| + }));
|
| + controller = createShadowInjector(injector, templateLoader).get(type);
|
| + ComponentFactory._setupOnShadowDomAttach(controller, templateLoader, shadowScope);
|
| + return controller;
|
| + }
|
| +
|
| + dom.ShadowRoot attachViewToShadowDom(ViewFactory viewFactory) {
|
| + var view = viewFactory(shadowInjector);
|
| + shadowDom.nodes.addAll(view.nodes);
|
| + return shadowDom;
|
| + }
|
| +
|
| + Injector createShadowInjector(injector, TemplateLoader templateLoader) {
|
| + var probe;
|
| + var shadowModule = new Module()
|
| + ..type(type)
|
| + ..type(NgElement)
|
| + ..type(EventHandler, implementedBy: ShadowRootEventHandler)
|
| + ..value(Scope, shadowScope)
|
| + ..value(TemplateLoader, templateLoader)
|
| + ..value(dom.ShadowRoot, shadowDom)
|
| + ..factory(ElementProbe, (_) => probe);
|
| + shadowInjector = injector.createChild([shadowModule], name: SHADOW_DOM_INJECTOR_NAME);
|
| + probe = _expando[shadowDom] = new ElementProbe(
|
| + injector.get(ElementProbe), shadowDom, shadowInjector, shadowScope);
|
| + return shadowInjector;
|
| + }
|
| +}
|
|
|