feat(ShadowDomStrategy): implemented EmulatedUnscopedShadowDomStrategy
- The new strategy do not scope component styles but make them global, - The former EmulatedShadowStrategy has been renamed to EmulatedScopedShadowDomStrategy. It does scope the styles.
This commit is contained in:
@ -12,7 +12,7 @@ import {ElementBinderBuilder} from './element_binder_builder';
|
||||
import {ResolveCss} from './resolve_css';
|
||||
import {ShimShadowDom} from './shim_shadow_dom';
|
||||
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
|
||||
import {ShadowDomStrategy, EmulatedShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||
import {ShadowDomStrategy, EmulatedScopedShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
|
||||
|
||||
/**
|
||||
* Default steps used for compiling a template.
|
||||
@ -39,7 +39,7 @@ export function createDefaultSteps(
|
||||
new ElementBinderBuilder(parser),
|
||||
];
|
||||
|
||||
if (shadowDomStrategy instanceof EmulatedShadowDomStrategy) {
|
||||
if (shadowDomStrategy instanceof EmulatedScopedShadowDomStrategy) {
|
||||
var step = new ShimShadowDom(compiledComponent, shadowDomStrategy);
|
||||
ListWrapper.push(steps, step);
|
||||
}
|
||||
|
@ -23,15 +23,22 @@ export class ShadowDomStrategy {
|
||||
shimHostElement(component: Type, element: Element) {}
|
||||
}
|
||||
|
||||
export class EmulatedShadowDomStrategy extends ShadowDomStrategy {
|
||||
_styleInliner: StyleInliner;
|
||||
/**
|
||||
* This strategy emulates the Shadow DOM for the templates, styles **excluded**:
|
||||
* - components templates are added as children of their component element,
|
||||
* - styles are moved from the templates to the styleHost (i.e. the document head).
|
||||
*
|
||||
* Notes:
|
||||
* - styles are **not** scoped to their component and will apply to the whole document,
|
||||
* - you can **not** use shadow DOM specific selectors in the styles
|
||||
*/
|
||||
export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
|
||||
_styleUrlResolver: StyleUrlResolver;
|
||||
_styleHost: Element;
|
||||
_lastInsertedStyle: StyleElement;
|
||||
_styleHost: Element;
|
||||
|
||||
constructor(styleInliner: StyleInliner, styleUrlResolver: StyleUrlResolver, styleHost: Element) {
|
||||
constructor(styleUrlResolver: StyleUrlResolver, styleHost: Element) {
|
||||
super();
|
||||
this._styleInliner = styleInliner;
|
||||
this._styleUrlResolver = styleUrlResolver;
|
||||
this._styleHost = styleHost;
|
||||
}
|
||||
@ -49,6 +56,58 @@ export class EmulatedShadowDomStrategy extends ShadowDomStrategy {
|
||||
return [Content];
|
||||
}
|
||||
|
||||
transformStyleText(cssText: string, baseUrl: string, component: Type) {
|
||||
return this._styleUrlResolver.resolveUrls(cssText, baseUrl);
|
||||
}
|
||||
|
||||
handleStyleElement(styleEl: StyleElement) {
|
||||
DOM.remove(styleEl);
|
||||
|
||||
var cssText = DOM.getText(styleEl);
|
||||
|
||||
if (!MapWrapper.contains(_sharedStyleTexts, cssText)) {
|
||||
// Styles are unscoped and shared across components, only append them to the head
|
||||
// when there are not present yet
|
||||
MapWrapper.set(_sharedStyleTexts, cssText, true);
|
||||
this._insertStyleElement(this._styleHost, styleEl);
|
||||
}
|
||||
};
|
||||
|
||||
_insertStyleElement(host: Element, style: StyleElement) {
|
||||
if (isBlank(this._lastInsertedStyle)) {
|
||||
var firstChild = DOM.firstChild(host);
|
||||
if (isPresent(firstChild)) {
|
||||
DOM.insertBefore(firstChild, style);
|
||||
} else {
|
||||
DOM.appendChild(host, style);
|
||||
}
|
||||
} else {
|
||||
DOM.insertAfter(this._lastInsertedStyle, style);
|
||||
}
|
||||
this._lastInsertedStyle = style;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This strategy emulates the Shadow DOM for the templates, styles **included**:
|
||||
* - components templates are added as children of their component element,
|
||||
* - both the template and the styles are modified so that styles are scoped to the component
|
||||
* they belong to,
|
||||
* - styles are moved from the templates to the styleHost (i.e. the document head).
|
||||
*
|
||||
* Notes:
|
||||
* - styles are scoped to their component and will apply only to it,
|
||||
* - a common subset of shadow DOM selectors are supported,
|
||||
* - see `ShadowCss` for more information and limitations.
|
||||
*/
|
||||
export class EmulatedScopedShadowDomStrategy extends EmulatedUnscopedShadowDomStrategy {
|
||||
_styleInliner: StyleInliner;
|
||||
|
||||
constructor(styleInliner: StyleInliner, styleUrlResolver: StyleUrlResolver, styleHost: Element) {
|
||||
super(styleUrlResolver, styleHost);
|
||||
this._styleInliner = styleInliner;
|
||||
}
|
||||
|
||||
transformStyleText(cssText: string, baseUrl: string, component: Type) {
|
||||
cssText = this._styleUrlResolver.resolveUrls(cssText, baseUrl);
|
||||
var css = this._styleInliner.inlineImports(cssText, baseUrl);
|
||||
@ -75,22 +134,14 @@ export class EmulatedShadowDomStrategy extends ShadowDomStrategy {
|
||||
var attrName = _getHostAttribute(id);
|
||||
DOM.setAttribute(element, attrName, '');
|
||||
}
|
||||
|
||||
_insertStyleElement(host: Element, style: StyleElement) {
|
||||
if (isBlank(this._lastInsertedStyle)) {
|
||||
var firstChild = DOM.firstChild(host);
|
||||
if (isPresent(firstChild)) {
|
||||
DOM.insertBefore(firstChild, style);
|
||||
} else {
|
||||
DOM.appendChild(host, style);
|
||||
}
|
||||
} else {
|
||||
DOM.insertAfter(this._lastInsertedStyle, style);
|
||||
}
|
||||
this._lastInsertedStyle = style;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This strategies uses the native Shadow DOM support.
|
||||
*
|
||||
* The templates for the component are inserted in a Shadow Root created on the component element.
|
||||
* Hence they are strictly isolated.
|
||||
*/
|
||||
export class NativeShadowDomStrategy extends ShadowDomStrategy {
|
||||
_styleUrlResolver: StyleUrlResolver;
|
||||
|
||||
@ -124,6 +175,7 @@ function _moveViewNodesIntoParent(parent, view) {
|
||||
|
||||
var _componentUIDs: Map<Type, int> = MapWrapper.create();
|
||||
var _nextComponentUID: int = 0;
|
||||
var _sharedStyleTexts: Map<string, boolean> = MapWrapper.create();
|
||||
|
||||
function _getComponentId(component: Type) {
|
||||
var id = MapWrapper.get(_componentUIDs, component);
|
||||
@ -150,8 +202,9 @@ function _shimCssForComponent(cssText: string, component: Type): string {
|
||||
return shadowCss.shimCssText(cssText, _getContentAttribute(id), _getHostAttribute(id));
|
||||
}
|
||||
|
||||
// Reset the component cache - used for tests only
|
||||
// Reset the caches - used for tests only
|
||||
export function resetShadowDomCache() {
|
||||
MapWrapper.clear(_componentUIDs);
|
||||
_nextComponentUID = 0;
|
||||
MapWrapper.clear(_sharedStyleTexts);
|
||||
}
|
||||
|
Reference in New Issue
Block a user