refactor(render): ts’ify render api
This commit is contained in:
parent
bd8724e652
commit
1beadb8607
@ -2,12 +2,17 @@
|
|||||||
* This file contains declarations of global symbols we reference in our code
|
* This file contains declarations of global symbols we reference in our code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// <reference path="typings/hammerjs/hammerjs"/>
|
||||||
|
/// <reference path="typings/zone/zone.d.ts"/>
|
||||||
|
|
||||||
declare var assert: any;
|
declare var assert: any;
|
||||||
declare var global: Window;
|
declare var global: Window;
|
||||||
type int = number;
|
type int = number;
|
||||||
|
|
||||||
interface List<T> extends Array<T> {}
|
interface List<T> extends Array<T> {}
|
||||||
|
|
||||||
|
interface StringMap<K,V> extends Object {}
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
Object: typeof Object;
|
Object: typeof Object;
|
||||||
Array: typeof Array;
|
Array: typeof Array;
|
||||||
@ -20,4 +25,6 @@ interface Window {
|
|||||||
assert: typeof assert;
|
assert: typeof assert;
|
||||||
gc(): void;
|
gc(): void;
|
||||||
Reflect: any;
|
Reflect: any;
|
||||||
|
zone: Zone;
|
||||||
|
Hammer: HammerStatic;
|
||||||
}
|
}
|
||||||
|
4
modules/angular2/src/core/compiler/view.js
vendored
4
modules/angular2/src/core/compiler/view.js
vendored
@ -6,6 +6,7 @@ import {ProtoElementInjector, ElementInjector, PreBuiltObjects, DirectiveBinding
|
|||||||
import {ElementBinder} from './element_binder';
|
import {ElementBinder} from './element_binder';
|
||||||
import {IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
import {IMPLEMENTS, int, isPresent, isBlank, BaseException} from 'angular2/src/facade/lang';
|
||||||
import * as renderApi from 'angular2/src/render/api';
|
import * as renderApi from 'angular2/src/render/api';
|
||||||
|
import {EventDispatcher} from 'angular2/src/render/api';
|
||||||
|
|
||||||
export class AppViewContainer {
|
export class AppViewContainer {
|
||||||
views: List<AppView>;
|
views: List<AppView>;
|
||||||
@ -21,8 +22,7 @@ export class AppViewContainer {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@IMPLEMENTS(ChangeDispatcher)
|
@IMPLEMENTS(ChangeDispatcher)
|
||||||
// TODO(tbosch): this is not supported in dart2js (no '.' is allowed)
|
@IMPLEMENTS(EventDispatcher)
|
||||||
// @IMPLEMENTS(renderApi.EventDispatcher)
|
|
||||||
export class AppView {
|
export class AppView {
|
||||||
render:renderApi.RenderViewRef;
|
render:renderApi.RenderViewRef;
|
||||||
/// This list matches the _nodes list. It is sparse, since only Elements have ElementInjector
|
/// This list matches the _nodes list. It is sparse, since only Elements have ElementInjector
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
// TODO(vicb): implement this class properly
|
|
||||||
// The current stub implementation is only here to please cjs tests
|
|
||||||
export class NgZone {
|
|
||||||
constructor({enableLongStackTrace}) {
|
|
||||||
}
|
|
||||||
|
|
||||||
initCallbacks({onTurnStart, onTurnDone, onScheduleMicrotask, onErrorHandler} = {}) {
|
|
||||||
}
|
|
||||||
|
|
||||||
run(fn) {
|
|
||||||
return fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
runOutsideAngular(fn) {
|
|
||||||
return fn();
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,12 +19,12 @@ export class NgZone {
|
|||||||
// onTurnDone hook at the end of the current VM turn.
|
// onTurnDone hook at the end of the current VM turn.
|
||||||
_innerZone;
|
_innerZone;
|
||||||
|
|
||||||
_onTurnStart:Function;
|
_onTurnStart: () => void;
|
||||||
_onTurnDone:Function;
|
_onTurnDone: () => void;
|
||||||
_onErrorHandler:Function;
|
_onErrorHandler: (error, stack) => void;
|
||||||
|
|
||||||
// Number of microtasks pending from _innerZone (& descendants)
|
// Number of microtasks pending from _innerZone (& descendants)
|
||||||
_pendingMicrotask: number;
|
_pendingMicrotasks: number;
|
||||||
// Whether some code has been executed in the _innerZone (& descendants) in the current turn
|
// Whether some code has been executed in the _innerZone (& descendants) in the current turn
|
||||||
_hasExecutedCodeInInnerZone: boolean;
|
_hasExecutedCodeInInnerZone: boolean;
|
||||||
// run() call depth in _mountZone. 0 at the end of a macrotask
|
// run() call depth in _mountZone. 0 at the end of a macrotask
|
||||||
@ -32,6 +32,10 @@ export class NgZone {
|
|||||||
// zone.run(() => {}); // nested call -> in-turn
|
// zone.run(() => {}); // nested call -> in-turn
|
||||||
// });
|
// });
|
||||||
_nestedRun: number;
|
_nestedRun: number;
|
||||||
|
|
||||||
|
// TODO(vicb): implement this class properly for node.js environment
|
||||||
|
// This disabled flag is only here to please cjs tests
|
||||||
|
_disabled: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associates with this
|
* Associates with this
|
||||||
@ -50,19 +54,31 @@ export class NgZone {
|
|||||||
this._pendingMicrotasks = 0;
|
this._pendingMicrotasks = 0;
|
||||||
this._hasExecutedCodeInInnerZone = false;
|
this._hasExecutedCodeInInnerZone = false;
|
||||||
this._nestedRun = 0;
|
this._nestedRun = 0;
|
||||||
|
|
||||||
this._mountZone = global.zone;
|
if (global.zone) {
|
||||||
this._innerZone = this._createInnerZone(this._mountZone, enableLongStackTrace)
|
this._disabled = false;
|
||||||
|
this._mountZone = global.zone;
|
||||||
|
this._innerZone = this._createInnerZone(this._mountZone, enableLongStackTrace)
|
||||||
|
} else {
|
||||||
|
this._disabled = true;
|
||||||
|
this._mountZone = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the zone hooks.
|
* Initializes the zone hooks.
|
||||||
*
|
*
|
||||||
* @param {Function} onTurnStart called before code executes in the inner zone for each VM turn
|
* @param {() => void} onTurnStart called before code executes in the inner zone for each VM turn
|
||||||
* @param {Function} onTurnDone called at the end of a VM turn if code has executed in the inner zone
|
* @param {() => void} onTurnDone called at the end of a VM turn if code has executed in the inner
|
||||||
* @param {Function} onErrorHandler called when an exception is thrown by a macro or micro task
|
* zone
|
||||||
|
* @param {(error, stack) => void} onErrorHandler called when an exception is thrown by a macro or
|
||||||
|
* micro task
|
||||||
*/
|
*/
|
||||||
initCallbacks({onTurnStart, onTurnDone, onErrorHandler} = {}) {
|
initCallbacks({onTurnStart, onTurnDone, onErrorHandler}: {
|
||||||
|
onTurnStart?: () => void,
|
||||||
|
onTurnDone?: () => void,
|
||||||
|
onErrorHandler?: (error, stack) => void
|
||||||
|
} = {}) {
|
||||||
this._onTurnStart = normalizeBlank(onTurnStart);
|
this._onTurnStart = normalizeBlank(onTurnStart);
|
||||||
this._onTurnDone = normalizeBlank(onTurnDone);
|
this._onTurnDone = normalizeBlank(onTurnDone);
|
||||||
this._onErrorHandler = normalizeBlank(onErrorHandler);
|
this._onErrorHandler = normalizeBlank(onErrorHandler);
|
||||||
@ -78,12 +94,17 @@ export class NgZone {
|
|||||||
* var zone: NgZone = [ref to the application zone];
|
* var zone: NgZone = [ref to the application zone];
|
||||||
*
|
*
|
||||||
* zone.run(() => {
|
* zone.run(() => {
|
||||||
* // the change detection will run after this function and the microtasks it enqueues have executed.
|
* // the change detection will run after this function and the microtasks it enqueues have
|
||||||
|
* executed.
|
||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
run(fn) {
|
run(fn) {
|
||||||
return this._innerZone.run(fn);
|
if (this._disabled) {
|
||||||
|
return fn();
|
||||||
|
} else {
|
||||||
|
return this._innerZone.run(fn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,8 +123,12 @@ export class NgZone {
|
|||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
runOutsideAngular(fn) {
|
runOutsideAngular(fn) {
|
||||||
return this._mountZone.run(fn);
|
if (this._disabled) {
|
||||||
|
return fn();
|
||||||
|
} else {
|
||||||
|
return this._mountZone.run(fn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_createInnerZone(zone, enableLongStackTrace) {
|
_createInnerZone(zone, enableLongStackTrace) {
|
||||||
@ -111,21 +136,15 @@ export class NgZone {
|
|||||||
var errorHandling;
|
var errorHandling;
|
||||||
|
|
||||||
if (enableLongStackTrace) {
|
if (enableLongStackTrace) {
|
||||||
errorHandling = StringMapWrapper.merge(Zone.longStackTraceZone, {
|
errorHandling = StringMapWrapper.merge(Zone.longStackTraceZone,
|
||||||
onError: function (e) {
|
{onError: function(e) { ngZone._onError(this, e) }});
|
||||||
ngZone._onError(this, e)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
errorHandling = {
|
errorHandling = {
|
||||||
onError: function (e) {
|
onError: function(e) { ngZone._onError(this, e) }
|
||||||
ngZone._onError(this, e)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return zone
|
return zone.fork(errorHandling)
|
||||||
.fork(errorHandling)
|
|
||||||
.fork({
|
.fork({
|
||||||
'$run': function(parentRun) {
|
'$run': function(parentRun) {
|
||||||
return function() {
|
return function() {
|
||||||
@ -140,8 +159,10 @@ export class NgZone {
|
|||||||
return parentRun.apply(this, arguments);
|
return parentRun.apply(this, arguments);
|
||||||
} finally {
|
} finally {
|
||||||
ngZone._nestedRun--;
|
ngZone._nestedRun--;
|
||||||
// If there are no more pending microtasks, we are at the end of a VM turn (or in onTurnStart)
|
// If there are no more pending microtasks, we are at the end of a VM turn (or in
|
||||||
// _nestedRun will be 0 at the end of a macrotasks (it could be > 0 when there are nested calls
|
// onTurnStart)
|
||||||
|
// _nestedRun will be 0 at the end of a macrotasks (it could be > 0 when there are
|
||||||
|
// nested calls
|
||||||
// to run()).
|
// to run()).
|
||||||
if (ngZone._pendingMicrotasks == 0 && ngZone._nestedRun == 0) {
|
if (ngZone._pendingMicrotasks == 0 && ngZone._nestedRun == 0) {
|
||||||
if (ngZone._onTurnDone && ngZone._hasExecutedCodeInInnerZone) {
|
if (ngZone._onTurnDone && ngZone._hasExecutedCodeInInnerZone) {
|
@ -273,7 +273,7 @@ defaultDoc() {
|
|||||||
getBoundingClientRect(el) {
|
getBoundingClientRect(el) {
|
||||||
return el.getBoundingClientRect();
|
return el.getBoundingClientRect();
|
||||||
}
|
}
|
||||||
getTitle() {
|
getTitle(): string {
|
||||||
return document.title;
|
return document.title;
|
||||||
}
|
}
|
||||||
setTitle(newTitle: string) {
|
setTitle(newTitle: string) {
|
||||||
|
@ -81,7 +81,7 @@ export class DomAdapter {
|
|||||||
removeStyle(element, stylename: string) { throw _abstract(); }
|
removeStyle(element, stylename: string) { throw _abstract(); }
|
||||||
getStyle(element, stylename: string) { throw _abstract(); }
|
getStyle(element, stylename: string) { throw _abstract(); }
|
||||||
tagName(element): string { throw _abstract(); }
|
tagName(element): string { throw _abstract(); }
|
||||||
attributeMap(element) { throw _abstract(); }
|
attributeMap(element): Map<string, string> { throw _abstract(); }
|
||||||
hasAttribute(element, attribute: string): boolean { throw _abstract(); }
|
hasAttribute(element, attribute: string): boolean { throw _abstract(); }
|
||||||
getAttribute(element, attribute: string): string { throw _abstract(); }
|
getAttribute(element, attribute: string): string { throw _abstract(); }
|
||||||
setAttribute(element, name: string, value: string) { throw _abstract(); }
|
setAttribute(element, name: string, value: string) { throw _abstract(); }
|
||||||
@ -90,7 +90,7 @@ export class DomAdapter {
|
|||||||
createHtmlDocument() { throw _abstract(); }
|
createHtmlDocument() { throw _abstract(); }
|
||||||
defaultDoc(): any { throw _abstract(); }
|
defaultDoc(): any { throw _abstract(); }
|
||||||
getBoundingClientRect(el) { throw _abstract(); }
|
getBoundingClientRect(el) { throw _abstract(); }
|
||||||
getTitle() { throw _abstract(); }
|
getTitle(): string { throw _abstract(); }
|
||||||
setTitle(newTitle: string) { throw _abstract(); }
|
setTitle(newTitle: string) { throw _abstract(); }
|
||||||
elementMatches(n, selector: string): boolean { throw _abstract(); }
|
elementMatches(n, selector: string): boolean { throw _abstract(); }
|
||||||
isTemplateElement(el: any): boolean { throw _abstract(); }
|
isTemplateElement(el: any): boolean { throw _abstract(); }
|
||||||
|
@ -20,21 +20,21 @@ import {ASTWithSource} from 'angular2/change_detection';
|
|||||||
* its output will be stored in precompiled templates.
|
* its output will be stored in precompiled templates.
|
||||||
*/
|
*/
|
||||||
export class EventBinding {
|
export class EventBinding {
|
||||||
fullName: string; // name/target:name, e.g "click", "window:resize"
|
fullName: string; // name/target:name, e.g "click", "window:resize"
|
||||||
source: ASTWithSource;
|
source: ASTWithSource;
|
||||||
|
|
||||||
constructor(fullName :string, source: ASTWithSource) {
|
constructor(fullName: string, source: ASTWithSource) {
|
||||||
this.fullName = fullName;
|
this.fullName = fullName;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ElementBinder {
|
export class ElementBinder {
|
||||||
index:number;
|
index: number;
|
||||||
parentIndex:number;
|
parentIndex: number;
|
||||||
distanceToParent:number;
|
distanceToParent: number;
|
||||||
directives:List<DirectiveBinder>;
|
directives: List<DirectiveBinder>;
|
||||||
nestedProtoView:ProtoViewDto;
|
nestedProtoView: ProtoViewDto;
|
||||||
propertyBindings: Map<string, ASTWithSource>;
|
propertyBindings: Map<string, ASTWithSource>;
|
||||||
variableBindings: Map<string, ASTWithSource>;
|
variableBindings: Map<string, ASTWithSource>;
|
||||||
// Note: this contains a preprocessed AST
|
// Note: this contains a preprocessed AST
|
||||||
@ -50,7 +50,11 @@ export class ElementBinder {
|
|||||||
propertyBindings, variableBindings,
|
propertyBindings, variableBindings,
|
||||||
eventBindings, textBindings,
|
eventBindings, textBindings,
|
||||||
readAttributes
|
readAttributes
|
||||||
}) {
|
}:{index?:number, parentIndex?:number, distanceToParent?:number,
|
||||||
|
directives?:List<DirectiveBinder>, nestedProtoView?:ProtoViewDto,
|
||||||
|
propertyBindings?:Map<string, ASTWithSource>, variableBindings?:Map<string, ASTWithSource>,
|
||||||
|
eventBindings?:List<EventBinding>, textBindings?:List<ASTWithSource>,
|
||||||
|
readAttributes?:Map<string, string>}={}) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.parentIndex = parentIndex;
|
this.parentIndex = parentIndex;
|
||||||
this.distanceToParent = distanceToParent;
|
this.distanceToParent = distanceToParent;
|
||||||
@ -66,7 +70,7 @@ export class ElementBinder {
|
|||||||
|
|
||||||
export class DirectiveBinder {
|
export class DirectiveBinder {
|
||||||
// Index into the array of directives in the View instance
|
// Index into the array of directives in the View instance
|
||||||
directiveIndex:any;
|
directiveIndex: number;
|
||||||
propertyBindings: Map<string, ASTWithSource>;
|
propertyBindings: Map<string, ASTWithSource>;
|
||||||
// Note: this contains a preprocessed AST
|
// Note: this contains a preprocessed AST
|
||||||
// that replaced the values that should be extracted from the element
|
// that replaced the values that should be extracted from the element
|
||||||
@ -75,6 +79,9 @@ export class DirectiveBinder {
|
|||||||
hostPropertyBindings: Map<string, ASTWithSource>;
|
hostPropertyBindings: Map<string, ASTWithSource>;
|
||||||
constructor({
|
constructor({
|
||||||
directiveIndex, propertyBindings, eventBindings, hostPropertyBindings
|
directiveIndex, propertyBindings, eventBindings, hostPropertyBindings
|
||||||
|
}:{
|
||||||
|
directiveIndex?:number, propertyBindings?:Map<string, ASTWithSource>,
|
||||||
|
eventBindings?:List<EventBinding>, hostPropertyBindings?:Map<string, ASTWithSource>
|
||||||
}) {
|
}) {
|
||||||
this.directiveIndex = directiveIndex;
|
this.directiveIndex = directiveIndex;
|
||||||
this.propertyBindings = propertyBindings;
|
this.propertyBindings = propertyBindings;
|
||||||
@ -96,11 +103,16 @@ export class ProtoViewDto {
|
|||||||
static get EMBEDDED_VIEW_TYPE() { return 2; }
|
static get EMBEDDED_VIEW_TYPE() { return 2; }
|
||||||
|
|
||||||
render: RenderProtoViewRef;
|
render: RenderProtoViewRef;
|
||||||
elementBinders:List<ElementBinder>;
|
elementBinders: List<ElementBinder>;
|
||||||
variableBindings: Map<string, string>;
|
variableBindings: Map<string, string>;
|
||||||
type: number;
|
type: number;
|
||||||
|
|
||||||
constructor({render, elementBinders, variableBindings, type}={}) {
|
constructor({
|
||||||
|
render, elementBinders, variableBindings, type
|
||||||
|
}:{
|
||||||
|
render?:RenderProtoViewRef, elementBinders?:List<ElementBinder>,
|
||||||
|
variableBindings?:Map<string, string>, type?:number
|
||||||
|
}) {
|
||||||
this.render = render;
|
this.render = render;
|
||||||
this.elementBinders = elementBinders;
|
this.elementBinders = elementBinders;
|
||||||
this.variableBindings = variableBindings;
|
this.variableBindings = variableBindings;
|
||||||
@ -111,25 +123,31 @@ export class ProtoViewDto {
|
|||||||
export class DirectiveMetadata {
|
export class DirectiveMetadata {
|
||||||
static get DIRECTIVE_TYPE() { return 0; }
|
static get DIRECTIVE_TYPE() { return 0; }
|
||||||
static get COMPONENT_TYPE() { return 1; }
|
static get COMPONENT_TYPE() { return 1; }
|
||||||
id:any;
|
id: any;
|
||||||
selector:string;
|
selector: string;
|
||||||
compileChildren:boolean;
|
compileChildren: boolean;
|
||||||
events:List<string>;
|
events: List<string>;
|
||||||
hostListeners:Map<string, string>;
|
hostListeners: Map<string, string>;
|
||||||
hostProperties:Map<string, string>;
|
hostProperties: Map<string, string>;
|
||||||
hostAttributes:Map<string, string>;
|
hostAttributes: Map<string, string>;
|
||||||
hostActions:Map<string, string>;
|
hostActions: Map<string, string>;
|
||||||
properties:Map<string, string>;
|
properties: Map<string, string>;
|
||||||
readAttributes:List<string>;
|
readAttributes: List<string>;
|
||||||
type:number;
|
type: number;
|
||||||
callOnDestroy:boolean;
|
callOnDestroy: boolean;
|
||||||
callOnChange:boolean;
|
callOnChange: boolean;
|
||||||
callOnAllChangesDone:boolean;
|
callOnAllChangesDone: boolean;
|
||||||
changeDetection: string;
|
changeDetection: string;
|
||||||
constructor({id, selector, compileChildren, events, hostListeners, hostProperties,
|
constructor({
|
||||||
|
id, selector, compileChildren, events, hostListeners, hostProperties,
|
||||||
hostAttributes, hostActions, properties, readAttributes, type,
|
hostAttributes, hostActions, properties, readAttributes, type,
|
||||||
callOnDestroy, callOnChange, callOnAllChangesDone,
|
callOnDestroy, callOnChange, callOnAllChangesDone,
|
||||||
changeDetection
|
changeDetection
|
||||||
|
}:{
|
||||||
|
id?:string, selector?:string, compileChildren?:boolean, events?:List<string>, hostListeners?:Map<string, string>, hostProperties?:Map<string, string>,
|
||||||
|
hostAttributes?:Map<string, string>, hostActions?:Map<string, string>, properties?:Map<string, string>, readAttributes?:List<string>, type?:number,
|
||||||
|
callOnDestroy?:boolean, callOnChange?:boolean, callOnAllChangesDone?:boolean,
|
||||||
|
changeDetection?:string
|
||||||
}) {
|
}) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
@ -150,12 +168,10 @@ export class DirectiveMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// An opaque reference to a DomProtoView
|
// An opaque reference to a DomProtoView
|
||||||
export class RenderProtoViewRef {
|
export class RenderProtoViewRef {}
|
||||||
}
|
|
||||||
|
|
||||||
// An opaque reference to a DomView
|
// An opaque reference to a DomView
|
||||||
export class RenderViewRef {
|
export class RenderViewRef {}
|
||||||
}
|
|
||||||
|
|
||||||
export class ViewDefinition {
|
export class ViewDefinition {
|
||||||
componentId: string;
|
componentId: string;
|
||||||
@ -163,7 +179,11 @@ export class ViewDefinition {
|
|||||||
template: string;
|
template: string;
|
||||||
directives: List<DirectiveMetadata>;
|
directives: List<DirectiveMetadata>;
|
||||||
|
|
||||||
constructor({componentId, absUrl, template, directives}) {
|
constructor({
|
||||||
|
componentId, absUrl, template, directives
|
||||||
|
}:{
|
||||||
|
componentId?:string, absUrl?:string, template?:string, directives?:List<DirectiveMetadata>
|
||||||
|
}) {
|
||||||
this.componentId = componentId;
|
this.componentId = componentId;
|
||||||
this.absUrl = absUrl;
|
this.absUrl = absUrl;
|
||||||
this.template = template;
|
this.template = template;
|
||||||
@ -175,123 +195,120 @@ export class RenderCompiler {
|
|||||||
/**
|
/**
|
||||||
* Creats a ProtoViewDto that contains a single nested component with the given componentId.
|
* Creats a ProtoViewDto that contains a single nested component with the given componentId.
|
||||||
*/
|
*/
|
||||||
compileHost(componentId):Promise<ProtoViewDto> { return null; }
|
compileHost(directiveMetadata: DirectiveMetadata): Promise<ProtoViewDto> { return null; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles a single DomProtoView. Non recursive so that
|
* Compiles a single DomProtoView. Non recursive so that
|
||||||
* we don't need to serialize all possible components over the wire,
|
* we don't need to serialize all possible components over the wire,
|
||||||
* but only the needed ones based on previous calls.
|
* but only the needed ones based on previous calls.
|
||||||
*/
|
*/
|
||||||
compile(template:ViewDefinition):Promise<ProtoViewDto> { return null; }
|
compile(template: ViewDefinition): Promise<ProtoViewDto> { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Renderer {
|
export class Renderer {
|
||||||
/**
|
/**
|
||||||
* Creates a root host view that includes the given element.
|
* Creates a root host view that includes the given element.
|
||||||
* @param {RenderProtoViewRef} hostProtoViewRef a RenderProtoViewRef of type ProtoViewDto.HOST_VIEW_TYPE
|
* @param {RenderProtoViewRef} hostProtoViewRef a RenderProtoViewRef of type
|
||||||
* @param {any} hostElementSelector css selector for the host element (will be queried against the main document)
|
* ProtoViewDto.HOST_VIEW_TYPE
|
||||||
|
* @param {any} hostElementSelector css selector for the host element (will be queried against the
|
||||||
|
* main document)
|
||||||
* @return {RenderViewRef} the created view
|
* @return {RenderViewRef} the created view
|
||||||
*/
|
*/
|
||||||
createRootHostView(hostProtoViewRef:RenderProtoViewRef, hostElementSelector:string):RenderViewRef {
|
createRootHostView(hostProtoViewRef: RenderProtoViewRef,
|
||||||
|
hostElementSelector: string): RenderViewRef {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches a free host view's element from the DOM.
|
* Detaches a free host view's element from the DOM.
|
||||||
*/
|
*/
|
||||||
detachFreeHostView(parentHostViewRef:RenderViewRef, hostViewRef:RenderViewRef) {
|
detachFreeHostView(parentHostViewRef: RenderViewRef, hostViewRef: RenderViewRef) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a regular view out of the given ProtoView
|
* Creates a regular view out of the given ProtoView
|
||||||
*/
|
*/
|
||||||
createView(protoViewRef:RenderProtoViewRef):RenderViewRef {
|
createView(protoViewRef: RenderProtoViewRef): RenderViewRef { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the given view after it has been dehydrated and detached
|
* Destroys the given view after it has been dehydrated and detached
|
||||||
*/
|
*/
|
||||||
destroyView(viewRef:RenderViewRef) {
|
destroyView(viewRef: RenderViewRef) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a componentView into the given hostView at the given element
|
* Attaches a componentView into the given hostView at the given element
|
||||||
*/
|
*/
|
||||||
attachComponentView(hostViewRef:RenderViewRef, elementIndex:number, componentViewRef:RenderViewRef) {
|
attachComponentView(hostViewRef: RenderViewRef, elementIndex: number,
|
||||||
}
|
componentViewRef: RenderViewRef) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches a componentView into the given hostView at the given element
|
* Detaches a componentView into the given hostView at the given element
|
||||||
*/
|
*/
|
||||||
detachComponentView(hostViewRef:RenderViewRef, boundElementIndex:number, componentViewRef:RenderViewRef) {
|
detachComponentView(hostViewRef: RenderViewRef, boundElementIndex: number,
|
||||||
}
|
componentViewRef: RenderViewRef) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a view into a ViewContainer (in the given parentView at the given element) at the given index.
|
* Attaches a view into a ViewContainer (in the given parentView at the given element) at the
|
||||||
|
* given index.
|
||||||
*/
|
*/
|
||||||
attachViewInContainer(parentViewRef:RenderViewRef, boundElementIndex:number, atIndex:number, viewRef:RenderViewRef) {
|
attachViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
|
||||||
}
|
viewRef: RenderViewRef) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches a view into a ViewContainer (in the given parentView at the given element) at the given index.
|
* Detaches a view into a ViewContainer (in the given parentView at the given element) at the
|
||||||
|
* given index.
|
||||||
*/
|
*/
|
||||||
// TODO(tbosch): this should return a promise as it can be animated!
|
// TODO(tbosch): this should return a promise as it can be animated!
|
||||||
detachViewInContainer(parentViewRef:RenderViewRef, boundElementIndex:number, atIndex:number, viewRef:RenderViewRef) {
|
detachViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
|
||||||
}
|
viewRef: RenderViewRef) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hydrates a view after it has been attached. Hydration/dehydration is used for reusing views inside of the view pool.
|
* Hydrates a view after it has been attached. Hydration/dehydration is used for reusing views
|
||||||
|
* inside of the view pool.
|
||||||
*/
|
*/
|
||||||
hydrateView(viewRef:RenderViewRef) {
|
hydrateView(viewRef: RenderViewRef) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dehydrates a view after it has been attached. Hydration/dehydration is used for reusing views inside of the view pool.
|
* Dehydrates a view after it has been attached. Hydration/dehydration is used for reusing views
|
||||||
|
* inside of the view pool.
|
||||||
*/
|
*/
|
||||||
dehydrateView(viewRef:RenderViewRef) {
|
dehydrateView(viewRef: RenderViewRef) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a property on an element.
|
* Sets a property on an element.
|
||||||
* Note: This will fail if the property was not mentioned previously as a host property
|
* Note: This will fail if the property was not mentioned previously as a host property
|
||||||
* in the ProtoView
|
* in the ProtoView
|
||||||
*/
|
*/
|
||||||
setElementProperty(viewRef:RenderViewRef, elementIndex:number, propertyName:string, propertyValue:any):void {
|
setElementProperty(viewRef: RenderViewRef, elementIndex: number, propertyName: string,
|
||||||
}
|
propertyValue: any) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls an action.
|
* Calls an action.
|
||||||
* Note: This will fail if the action was not mentioned previously as a host action
|
* Note: This will fail if the action was not mentioned previously as a host action
|
||||||
* in the ProtoView
|
* in the ProtoView
|
||||||
*/
|
*/
|
||||||
callAction(viewRef:RenderViewRef, elementIndex:number, actionExpression:string, actionArgs:any):void {
|
callAction(viewRef: RenderViewRef, elementIndex: number, actionExpression: string,
|
||||||
}
|
actionArgs: any) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the value of a text node.
|
* Sets the value of a text node.
|
||||||
*/
|
*/
|
||||||
setText(viewRef:RenderViewRef, textNodeIndex:number, text:string):void {
|
setText(viewRef: RenderViewRef, textNodeIndex: number, text: string) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the dispatcher for all events of the given view
|
* Sets the dispatcher for all events of the given view
|
||||||
*/
|
*/
|
||||||
setEventDispatcher(viewRef:RenderViewRef, dispatcher:any/*api.EventDispatcher*/):void {
|
setEventDispatcher(viewRef: RenderViewRef, dispatcher: EventDispatcher) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A dispatcher for all events happening in a view.
|
* A dispatcher for all events happening in a view.
|
||||||
*/
|
*/
|
||||||
export class EventDispatcher {
|
export interface EventDispatcher {
|
||||||
/**
|
/**
|
||||||
* Called when an event was triggered for a on-* attribute on an element.
|
* Called when an event was triggered for a on-* attribute on an element.
|
||||||
* @param {Map<string, any>} locals Locals to be used to evaluate the
|
* @param {Map<string, any>} locals Locals to be used to evaluate the
|
||||||
* event expressions
|
* event expressions
|
||||||
*/
|
*/
|
||||||
dispatchEvent(
|
dispatchEvent(elementIndex: number, eventName: string, locals: Map<string, any>);
|
||||||
elementIndex:number, eventName:string, locals:Map<string, any>
|
|
||||||
):void {}
|
|
||||||
}
|
}
|
@ -8,9 +8,9 @@ import {CompileStep} from './compile_step';
|
|||||||
* Right now it only allows to add a parent element.
|
* Right now it only allows to add a parent element.
|
||||||
*/
|
*/
|
||||||
export class CompileControl {
|
export class CompileControl {
|
||||||
_steps:List<CompileStep>;
|
_steps: List<CompileStep>;
|
||||||
_currentStepIndex:number;
|
_currentStepIndex: number;
|
||||||
_parent:CompileElement;
|
_parent: CompileElement;
|
||||||
_results;
|
_results;
|
||||||
_additionalChildren;
|
_additionalChildren;
|
||||||
_ignoreCurrentElement: boolean;
|
_ignoreCurrentElement: boolean;
|
||||||
@ -24,16 +24,14 @@ export class CompileControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// only public so that it can be used by compile_pipeline
|
// only public so that it can be used by compile_pipeline
|
||||||
internalProcess(results, startStepIndex, parent:CompileElement, current:CompileElement) {
|
internalProcess(results, startStepIndex, parent: CompileElement, current: CompileElement) {
|
||||||
this._results = results;
|
this._results = results;
|
||||||
var previousStepIndex = this._currentStepIndex;
|
var previousStepIndex = this._currentStepIndex;
|
||||||
var previousParent = this._parent;
|
var previousParent = this._parent;
|
||||||
|
|
||||||
this._ignoreCurrentElement = false;
|
this._ignoreCurrentElement = false;
|
||||||
|
|
||||||
for (var i = startStepIndex;
|
for (var i = startStepIndex; i < this._steps.length && !this._ignoreCurrentElement; i++) {
|
||||||
i < this._steps.length && !this._ignoreCurrentElement;
|
|
||||||
i++) {
|
|
||||||
var step = this._steps[i];
|
var step = this._steps[i];
|
||||||
this._parent = parent;
|
this._parent = parent;
|
||||||
this._currentStepIndex = i;
|
this._currentStepIndex = i;
|
||||||
@ -53,12 +51,12 @@ export class CompileControl {
|
|||||||
return localAdditionalChildren;
|
return localAdditionalChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
addParent(newElement:CompileElement) {
|
addParent(newElement: CompileElement) {
|
||||||
this.internalProcess(this._results, this._currentStepIndex+1, this._parent, newElement);
|
this.internalProcess(this._results, this._currentStepIndex + 1, this._parent, newElement);
|
||||||
this._parent = newElement;
|
this._parent = newElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
addChild(element:CompileElement) {
|
addChild(element: CompileElement) {
|
||||||
if (isBlank(this._additionalChildren)) {
|
if (isBlank(this._additionalChildren)) {
|
||||||
this._additionalChildren = ListWrapper.create();
|
this._additionalChildren = ListWrapper.create();
|
||||||
}
|
}
|
||||||
@ -71,7 +69,5 @@ export class CompileControl {
|
|||||||
* When a step calls `ignoreCurrentElement`, no further steps are executed on the current
|
* When a step calls `ignoreCurrentElement`, no further steps are executed on the current
|
||||||
* element and no `CompileElement` is added to the result list.
|
* element and no `CompileElement` is added to the result list.
|
||||||
*/
|
*/
|
||||||
ignoreCurrentElement() {
|
ignoreCurrentElement() { this._ignoreCurrentElement = true; }
|
||||||
this._ignoreCurrentElement = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,6 +1,13 @@
|
|||||||
import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {int, isBlank, isPresent, Type, StringJoiner, assertionsEnabled} from 'angular2/src/facade/lang';
|
import {
|
||||||
|
int,
|
||||||
|
isBlank,
|
||||||
|
isPresent,
|
||||||
|
Type,
|
||||||
|
StringJoiner,
|
||||||
|
assertionsEnabled
|
||||||
|
} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
import {ProtoViewBuilder, ElementBinderBuilder} from '../view/proto_view_builder';
|
import {ProtoViewBuilder, ElementBinderBuilder} from '../view/proto_view_builder';
|
||||||
|
|
||||||
@ -11,14 +18,15 @@ import {ProtoViewBuilder, ElementBinderBuilder} from '../view/proto_view_builder
|
|||||||
*/
|
*/
|
||||||
export class CompileElement {
|
export class CompileElement {
|
||||||
element;
|
element;
|
||||||
_attrs:Map;
|
_attrs: Map<string, string>;
|
||||||
_classList:List;
|
_classList: List<string>;
|
||||||
isViewRoot:boolean;
|
isViewRoot: boolean;
|
||||||
inheritedProtoView:ProtoViewBuilder;
|
inheritedProtoView: ProtoViewBuilder;
|
||||||
distanceToInheritedBinder:number;
|
distanceToInheritedBinder: number;
|
||||||
inheritedElementBinder:ElementBinderBuilder;
|
inheritedElementBinder: ElementBinderBuilder;
|
||||||
compileChildren: boolean;
|
compileChildren: boolean;
|
||||||
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of error
|
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of
|
||||||
|
// error
|
||||||
|
|
||||||
constructor(element, compilationUnit = '') {
|
constructor(element, compilationUnit = '') {
|
||||||
this.element = element;
|
this.element = element;
|
||||||
@ -34,7 +42,7 @@ export class CompileElement {
|
|||||||
this.distanceToInheritedBinder = 0;
|
this.distanceToInheritedBinder = 0;
|
||||||
this.compileChildren = true;
|
this.compileChildren = true;
|
||||||
// description is calculated here as compilation steps may change the element
|
// description is calculated here as compilation steps may change the element
|
||||||
var tplDesc = assertionsEnabled()? getElementDescription(element) : null;
|
var tplDesc = assertionsEnabled() ? getElementDescription(element) : null;
|
||||||
if (compilationUnit !== '') {
|
if (compilationUnit !== '') {
|
||||||
this.elementDescription = compilationUnit;
|
this.elementDescription = compilationUnit;
|
||||||
if (isPresent(tplDesc)) this.elementDescription += ": " + tplDesc;
|
if (isPresent(tplDesc)) this.elementDescription += ": " + tplDesc;
|
||||||
@ -50,7 +58,8 @@ export class CompileElement {
|
|||||||
bindElement() {
|
bindElement() {
|
||||||
if (!this.isBound()) {
|
if (!this.isBound()) {
|
||||||
var parentBinder = this.inheritedElementBinder;
|
var parentBinder = this.inheritedElementBinder;
|
||||||
this.inheritedElementBinder = this.inheritedProtoView.bindElement(this.element, this.elementDescription);
|
this.inheritedElementBinder =
|
||||||
|
this.inheritedProtoView.bindElement(this.element, this.elementDescription);
|
||||||
if (isPresent(parentBinder)) {
|
if (isPresent(parentBinder)) {
|
||||||
this.inheritedElementBinder.setParent(parentBinder, this.distanceToInheritedBinder);
|
this.inheritedElementBinder.setParent(parentBinder, this.distanceToInheritedBinder);
|
||||||
}
|
}
|
||||||
@ -59,22 +68,18 @@ export class CompileElement {
|
|||||||
return this.inheritedElementBinder;
|
return this.inheritedElementBinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshAttrs() {
|
refreshAttrs() { this._attrs = null; }
|
||||||
this._attrs = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrs():Map<string,string> {
|
attrs(): Map<string, string> {
|
||||||
if (isBlank(this._attrs)) {
|
if (isBlank(this._attrs)) {
|
||||||
this._attrs = DOM.attributeMap(this.element);
|
this._attrs = DOM.attributeMap(this.element);
|
||||||
}
|
}
|
||||||
return this._attrs;
|
return this._attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshClassList() {
|
refreshClassList() { this._classList = null; }
|
||||||
this._classList = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
classList():List<string> {
|
classList(): List<string> {
|
||||||
if (isBlank(this._classList)) {
|
if (isBlank(this._classList)) {
|
||||||
this._classList = ListWrapper.create();
|
this._classList = ListWrapper.create();
|
||||||
var elClassList = DOM.classList(this.element);
|
var elClassList = DOM.classList(this.element);
|
||||||
@ -84,12 +89,11 @@ export class CompileElement {
|
|||||||
}
|
}
|
||||||
return this._classList;
|
return this._classList;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return an HTML representation of an element start tag - without its content
|
// return an HTML representation of an element start tag - without its content
|
||||||
// this is used to give contextual information in case of errors
|
// this is used to give contextual information in case of errors
|
||||||
function getElementDescription(domElement):string {
|
function getElementDescription(domElement): string {
|
||||||
var buf = new StringJoiner();
|
var buf = new StringJoiner();
|
||||||
var atts = DOM.attributeMap(domElement);
|
var atts = DOM.attributeMap(domElement);
|
||||||
|
|
||||||
@ -100,9 +104,9 @@ function getElementDescription(domElement):string {
|
|||||||
addDescriptionAttribute(buf, "id", MapWrapper.get(atts, "id"));
|
addDescriptionAttribute(buf, "id", MapWrapper.get(atts, "id"));
|
||||||
addDescriptionAttribute(buf, "class", MapWrapper.get(atts, "class"));
|
addDescriptionAttribute(buf, "class", MapWrapper.get(atts, "class"));
|
||||||
MapWrapper.forEach(atts, (attValue, attName) => {
|
MapWrapper.forEach(atts, (attValue, attName) => {
|
||||||
if (attName !== "id" && attName !== "class") {
|
if (attName !== "id" && attName !== "class") {
|
||||||
addDescriptionAttribute(buf, attName, attValue);
|
addDescriptionAttribute(buf, attName, attValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
buf.add(">");
|
buf.add(">");
|
||||||
@ -110,12 +114,12 @@ function getElementDescription(domElement):string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function addDescriptionAttribute(buffer:StringJoiner, attName:string, attValue) {
|
function addDescriptionAttribute(buffer: StringJoiner, attName: string, attValue) {
|
||||||
if (isPresent(attValue)) {
|
if (isPresent(attValue)) {
|
||||||
if (attValue.length === 0) {
|
if (attValue.length === 0) {
|
||||||
buffer.add(' ' + attName);
|
buffer.add(' ' + attName);
|
||||||
} else {
|
} else {
|
||||||
buffer.add(' ' + attName + '="' + attValue + '"');
|
buffer.add(' ' + attName + '="' + attValue + '"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,12 +12,11 @@ import {ProtoViewDto} from '../../api';
|
|||||||
* all elements in a template.
|
* all elements in a template.
|
||||||
*/
|
*/
|
||||||
export class CompilePipeline {
|
export class CompilePipeline {
|
||||||
_control:CompileControl;
|
_control: CompileControl;
|
||||||
constructor(steps:List<CompileStep>) {
|
constructor(steps: List<CompileStep>) { this._control = new CompileControl(steps); }
|
||||||
this._control = new CompileControl(steps);
|
|
||||||
}
|
|
||||||
|
|
||||||
process(rootElement, protoViewType:number = null, compilationCtxtDescription:string = ''):List {
|
process(rootElement, protoViewType: number = null,
|
||||||
|
compilationCtxtDescription: string = ''): List<CompileElement> {
|
||||||
if (isBlank(protoViewType)) {
|
if (isBlank(protoViewType)) {
|
||||||
protoViewType = ProtoViewDto.COMPONENT_VIEW_TYPE;
|
protoViewType = ProtoViewDto.COMPONENT_VIEW_TYPE;
|
||||||
}
|
}
|
||||||
@ -25,13 +24,12 @@ export class CompilePipeline {
|
|||||||
var rootCompileElement = new CompileElement(rootElement, compilationCtxtDescription);
|
var rootCompileElement = new CompileElement(rootElement, compilationCtxtDescription);
|
||||||
rootCompileElement.inheritedProtoView = new ProtoViewBuilder(rootElement, protoViewType);
|
rootCompileElement.inheritedProtoView = new ProtoViewBuilder(rootElement, protoViewType);
|
||||||
rootCompileElement.isViewRoot = true;
|
rootCompileElement.isViewRoot = true;
|
||||||
this._process(results, null, rootCompileElement,
|
this._process(results, null, rootCompileElement, compilationCtxtDescription);
|
||||||
compilationCtxtDescription
|
|
||||||
);
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
_process(results, parent:CompileElement, current:CompileElement, compilationCtxtDescription:string = '') {
|
_process(results, parent: CompileElement, current: CompileElement,
|
||||||
|
compilationCtxtDescription: string = '') {
|
||||||
var additionalChildren = this._control.internalProcess(results, 0, parent, current);
|
var additionalChildren = this._control.internalProcess(results, 0, parent, current);
|
||||||
|
|
||||||
if (current.compileChildren) {
|
if (current.compileChildren) {
|
||||||
@ -44,7 +42,7 @@ export class CompilePipeline {
|
|||||||
var childCompileElement = new CompileElement(node, compilationCtxtDescription);
|
var childCompileElement = new CompileElement(node, compilationCtxtDescription);
|
||||||
childCompileElement.inheritedProtoView = current.inheritedProtoView;
|
childCompileElement.inheritedProtoView = current.inheritedProtoView;
|
||||||
childCompileElement.inheritedElementBinder = current.inheritedElementBinder;
|
childCompileElement.inheritedElementBinder = current.inheritedElementBinder;
|
||||||
childCompileElement.distanceToInheritedBinder = current.distanceToInheritedBinder+1;
|
childCompileElement.distanceToInheritedBinder = current.distanceToInheritedBinder + 1;
|
||||||
this._process(results, current, childCompileElement);
|
this._process(results, current, childCompileElement);
|
||||||
}
|
}
|
||||||
node = nextNode;
|
node = nextNode;
|
||||||
@ -52,7 +50,7 @@ export class CompilePipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(additionalChildren)) {
|
if (isPresent(additionalChildren)) {
|
||||||
for (var i=0; i<additionalChildren.length; i++) {
|
for (var i = 0; i < additionalChildren.length; i++) {
|
||||||
this._process(results, current, additionalChildren[i]);
|
this._process(results, current, additionalChildren[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,7 @@ import * as compileControlModule from './compile_control';
|
|||||||
* One part of the compile process.
|
* One part of the compile process.
|
||||||
* Is guaranteed to be called in depth first order
|
* Is guaranteed to be called in depth first order
|
||||||
*/
|
*/
|
||||||
export class CompileStep {
|
export interface CompileStep {
|
||||||
process(parent:CompileElement, current:CompileElement, control:compileControlModule.CompileControl) {}
|
process(parent: CompileElement, current: CompileElement,
|
||||||
|
control: compileControlModule.CompileControl): void;
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ import {ShadowDomCompileStep} from '../shadow_dom/shadow_dom_compile_step';
|
|||||||
import {ShadowDomStrategy} from '../shadow_dom/shadow_dom_strategy';
|
import {ShadowDomStrategy} from '../shadow_dom/shadow_dom_strategy';
|
||||||
|
|
||||||
export class CompileStepFactory {
|
export class CompileStepFactory {
|
||||||
createSteps(template: ViewDefinition, subTaskPromises: List<Promise>):List<CompileStep> {
|
createSteps(template: ViewDefinition, subTaskPromises: List<Promise<any>>): List<CompileStep> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ export class DefaultStepFactory extends CompileStepFactory {
|
|||||||
this._shadowDomStrategy = shadowDomStrategy;
|
this._shadowDomStrategy = shadowDomStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
createSteps(template: ViewDefinition, subTaskPromises: List<Promise>) {
|
createSteps(template: ViewDefinition, subTaskPromises: List<Promise<any>>) {
|
||||||
return [
|
return [
|
||||||
new ViewSplitter(this._parser),
|
new ViewSplitter(this._parser),
|
||||||
new PropertyBindingParser(this._parser),
|
new PropertyBindingParser(this._parser),
|
@ -1,10 +1,16 @@
|
|||||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
import {Injectable} from 'angular2/di';
|
||||||
|
|
||||||
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
import {BaseException, isPresent} from 'angular2/src/facade/lang';
|
import {BaseException, isPresent} from 'angular2/src/facade/lang';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
import {ViewDefinition, ProtoViewDto, DirectiveMetadata, RenderCompiler, RenderProtoViewRef} from '../../api';
|
import {
|
||||||
|
ViewDefinition,
|
||||||
|
ProtoViewDto,
|
||||||
|
DirectiveMetadata,
|
||||||
|
RenderCompiler,
|
||||||
|
RenderProtoViewRef
|
||||||
|
} from '../../api';
|
||||||
import {CompilePipeline} from './compile_pipeline';
|
import {CompilePipeline} from './compile_pipeline';
|
||||||
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
|
import {TemplateLoader} from 'angular2/src/render/dom/compiler/template_loader';
|
||||||
import {CompileStepFactory, DefaultStepFactory} from './compile_step_factory';
|
import {CompileStepFactory, DefaultStepFactory} from './compile_step_factory';
|
||||||
@ -26,26 +32,27 @@ export class DomCompiler extends RenderCompiler {
|
|||||||
this._stepFactory = stepFactory;
|
this._stepFactory = stepFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
compile(template: ViewDefinition):Promise<ProtoViewDto> {
|
compile(template: ViewDefinition): Promise<ProtoViewDto> {
|
||||||
var tplPromise = this._templateLoader.load(template);
|
var tplPromise = this._templateLoader.load(template);
|
||||||
return PromiseWrapper.then(tplPromise,
|
return PromiseWrapper.then(
|
||||||
(el) => this._compileTemplate(template, el, ProtoViewDto.COMPONENT_VIEW_TYPE),
|
tplPromise, (el) => this._compileTemplate(template, el, ProtoViewDto.COMPONENT_VIEW_TYPE),
|
||||||
(_) => { throw new BaseException(`Failed to load the template "${template.componentId}"`); }
|
(_) => {
|
||||||
);
|
throw new BaseException(`Failed to load the template "${template.componentId}"`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
compileHost(directiveMetadata: DirectiveMetadata):Promise<ProtoViewDto> {
|
compileHost(directiveMetadata: DirectiveMetadata): Promise<ProtoViewDto> {
|
||||||
var hostViewDef = new ViewDefinition({
|
var hostViewDef = new ViewDefinition({
|
||||||
componentId: directiveMetadata.id,
|
componentId: directiveMetadata.id,
|
||||||
absUrl: null,
|
absUrl: null, template: null,
|
||||||
template: null,
|
|
||||||
directives: [directiveMetadata]
|
directives: [directiveMetadata]
|
||||||
});
|
});
|
||||||
var element = DOM.createElement(directiveMetadata.selector);
|
var element = DOM.createElement(directiveMetadata.selector);
|
||||||
return this._compileTemplate(hostViewDef, element, ProtoViewDto.HOST_VIEW_TYPE);
|
return this._compileTemplate(hostViewDef, element, ProtoViewDto.HOST_VIEW_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
_compileTemplate(viewDef: ViewDefinition, tplElement, protoViewType:number):Promise<ProtoViewDto> {
|
_compileTemplate(viewDef: ViewDefinition, tplElement,
|
||||||
|
protoViewType: number): Promise<ProtoViewDto> {
|
||||||
var subTaskPromises = [];
|
var subTaskPromises = [];
|
||||||
var pipeline = new CompilePipeline(this._stepFactory.createSteps(viewDef, subTaskPromises));
|
var pipeline = new CompilePipeline(this._stepFactory.createSteps(viewDef, subTaskPromises));
|
||||||
var compileElements = pipeline.process(tplElement, protoViewType, viewDef.componentId);
|
var compileElements = pipeline.process(tplElement, protoViewType, viewDef.componentId);
|
||||||
@ -62,7 +69,8 @@ export class DomCompiler extends RenderCompiler {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DefaultDomCompiler extends DomCompiler {
|
export class DefaultDomCompiler extends DomCompiler {
|
||||||
constructor(parser:Parser, shadowDomStrategy:ShadowDomStrategy, templateLoader: TemplateLoader) {
|
constructor(parser: Parser, shadowDomStrategy: ShadowDomStrategy,
|
||||||
|
templateLoader: TemplateLoader) {
|
||||||
super(new DefaultStepFactory(parser, shadowDomStrategy), templateLoader);
|
super(new DefaultStepFactory(parser, shadowDomStrategy), templateLoader);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,11 @@
|
|||||||
import {isPresent, isBlank, BaseException, assertionsEnabled, RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
import {
|
||||||
|
isPresent,
|
||||||
|
isBlank,
|
||||||
|
BaseException,
|
||||||
|
assertionsEnabled,
|
||||||
|
RegExpWrapper,
|
||||||
|
StringWrapper
|
||||||
|
} from 'angular2/src/facade/lang';
|
||||||
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {Parser} from 'angular2/change_detection';
|
import {Parser} from 'angular2/change_detection';
|
||||||
@ -16,17 +23,16 @@ import {dashCaseToCamelCase, camelCaseToDashCase, EVENT_TARGET_SEPARATOR} from '
|
|||||||
* Parses the directives on a single element. Assumes ViewSplitter has already created
|
* Parses the directives on a single element. Assumes ViewSplitter has already created
|
||||||
* <template> elements for template directives.
|
* <template> elements for template directives.
|
||||||
*/
|
*/
|
||||||
export class DirectiveParser extends CompileStep {
|
export class DirectiveParser implements CompileStep {
|
||||||
_selectorMatcher:SelectorMatcher;
|
_selectorMatcher: SelectorMatcher;
|
||||||
_directives:List<DirectiveMetadata>;
|
_directives: List<DirectiveMetadata>;
|
||||||
_parser:Parser;
|
_parser: Parser;
|
||||||
|
|
||||||
constructor(parser: Parser, directives:List<DirectiveMetadata>) {
|
constructor(parser: Parser, directives: List<DirectiveMetadata>) {
|
||||||
super();
|
|
||||||
this._parser = parser;
|
this._parser = parser;
|
||||||
this._selectorMatcher = new SelectorMatcher();
|
this._selectorMatcher = new SelectorMatcher();
|
||||||
this._directives = directives;
|
this._directives = directives;
|
||||||
for (var i=0; i<directives.length; i++) {
|
for (var i = 0; i < directives.length; i++) {
|
||||||
var directive = directives[i];
|
var directive = directives[i];
|
||||||
var selector = CssSelector.parse(directive.selector);
|
var selector = CssSelector.parse(directive.selector);
|
||||||
this._ensureComponentOnlyHasElementSelector(selector, directive);
|
this._ensureComponentOnlyHasElementSelector(selector, directive);
|
||||||
@ -36,25 +42,25 @@ export class DirectiveParser extends CompileStep {
|
|||||||
|
|
||||||
_ensureComponentOnlyHasElementSelector(selector, directive) {
|
_ensureComponentOnlyHasElementSelector(selector, directive) {
|
||||||
var isElementSelector = selector.length === 1 && selector[0].isElementSelector();
|
var isElementSelector = selector.length === 1 && selector[0].isElementSelector();
|
||||||
if (! isElementSelector && directive.type === DirectiveMetadata.COMPONENT_TYPE) {
|
if (!isElementSelector && directive.type === DirectiveMetadata.COMPONENT_TYPE) {
|
||||||
throw new BaseException(`Component '${directive.id}' can only have an element selector, but had '${directive.selector}'`);
|
throw new BaseException(
|
||||||
|
`Component '${directive.id}' can only have an element selector, but had '${directive.selector}'`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
var attrs = current.attrs();
|
var attrs = current.attrs();
|
||||||
var classList = current.classList();
|
var classList = current.classList();
|
||||||
|
|
||||||
var cssSelector = new CssSelector();
|
var cssSelector = new CssSelector();
|
||||||
var nodeName = DOM.nodeName(current.element);
|
var nodeName = DOM.nodeName(current.element);
|
||||||
cssSelector.setElement(nodeName);
|
cssSelector.setElement(nodeName);
|
||||||
for (var i=0; i < classList.length; i++) {
|
for (var i = 0; i < classList.length; i++) {
|
||||||
cssSelector.addClassName(classList[i]);
|
cssSelector.addClassName(classList[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
MapWrapper.forEach(attrs, (attrValue, attrName) => {
|
MapWrapper.forEach(attrs,
|
||||||
cssSelector.addAttribute(attrName, attrValue);
|
(attrValue, attrName) => { cssSelector.addAttribute(attrName, attrValue); });
|
||||||
});
|
|
||||||
|
|
||||||
var componentDirective;
|
var componentDirective;
|
||||||
var foundDirectiveIndices = [];
|
var foundDirectiveIndices = [];
|
||||||
@ -66,7 +72,8 @@ export class DirectiveParser extends CompileStep {
|
|||||||
// components need to go first, so it is easier to locate them in the result.
|
// components need to go first, so it is easier to locate them in the result.
|
||||||
ListWrapper.insert(foundDirectiveIndices, 0, directiveIndex);
|
ListWrapper.insert(foundDirectiveIndices, 0, directiveIndex);
|
||||||
if (isPresent(componentDirective)) {
|
if (isPresent(componentDirective)) {
|
||||||
throw new BaseException(`Only one component directive is allowed per element - check ${current.elementDescription}`);
|
throw new BaseException(
|
||||||
|
`Only one component directive is allowed per element - check ${current.elementDescription}`);
|
||||||
}
|
}
|
||||||
componentDirective = directive;
|
componentDirective = directive;
|
||||||
elementBinder.setComponentId(directive.id);
|
elementBinder.setComponentId(directive.id);
|
||||||
@ -95,7 +102,8 @@ export class DirectiveParser extends CompileStep {
|
|||||||
}
|
}
|
||||||
if (isPresent(directive.hostProperties)) {
|
if (isPresent(directive.hostProperties)) {
|
||||||
MapWrapper.forEach(directive.hostProperties, (hostPropertyName, directivePropertyName) => {
|
MapWrapper.forEach(directive.hostProperties, (hostPropertyName, directivePropertyName) => {
|
||||||
this._bindHostProperty(hostPropertyName, directivePropertyName, current, directiveBinderBuilder);
|
this._bindHostProperty(hostPropertyName, directivePropertyName, current,
|
||||||
|
directiveBinderBuilder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (isPresent(directive.hostAttributes)) {
|
if (isPresent(directive.hostAttributes)) {
|
||||||
@ -104,9 +112,8 @@ export class DirectiveParser extends CompileStep {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (isPresent(directive.readAttributes)) {
|
if (isPresent(directive.readAttributes)) {
|
||||||
ListWrapper.forEach(directive.readAttributes, (attrName) => {
|
ListWrapper.forEach(directive.readAttributes,
|
||||||
elementBinder.readAttribute(attrName);
|
(attrName) => { elementBinder.readAttribute(attrName); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -115,27 +122,21 @@ export class DirectiveParser extends CompileStep {
|
|||||||
var pipes = this._splitBindConfig(bindConfig);
|
var pipes = this._splitBindConfig(bindConfig);
|
||||||
var elProp = ListWrapper.removeAt(pipes, 0);
|
var elProp = ListWrapper.removeAt(pipes, 0);
|
||||||
|
|
||||||
var bindingAst = MapWrapper.get(
|
var bindingAst =
|
||||||
compileElement.bindElement().propertyBindings,
|
MapWrapper.get(compileElement.bindElement().propertyBindings, dashCaseToCamelCase(elProp));
|
||||||
dashCaseToCamelCase(elProp)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isBlank(bindingAst)) {
|
if (isBlank(bindingAst)) {
|
||||||
var attributeValue = MapWrapper.get(compileElement.attrs(), camelCaseToDashCase(elProp));
|
var attributeValue = MapWrapper.get(compileElement.attrs(), camelCaseToDashCase(elProp));
|
||||||
if (isPresent(attributeValue)) {
|
if (isPresent(attributeValue)) {
|
||||||
bindingAst = this._parser.wrapLiteralPrimitive(
|
bindingAst =
|
||||||
attributeValue,
|
this._parser.wrapLiteralPrimitive(attributeValue, compileElement.elementDescription);
|
||||||
compileElement.elementDescription
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bindings are optional, so this binding only needs to be set up if an expression is given.
|
// Bindings are optional, so this binding only needs to be set up if an expression is given.
|
||||||
if (isPresent(bindingAst)) {
|
if (isPresent(bindingAst)) {
|
||||||
var fullExpAstWithBindPipes = this._parser.addPipes(bindingAst, pipes);
|
var fullExpAstWithBindPipes = this._parser.addPipes(bindingAst, pipes);
|
||||||
directiveBinderBuilder.bindProperty(
|
directiveBinderBuilder.bindProperty(dirProperty, fullExpAstWithBindPipes);
|
||||||
dirProperty, fullExpAstWithBindPipes
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,24 +155,23 @@ export class DirectiveParser extends CompileStep {
|
|||||||
directiveBinderBuilder.bindHostAction(actionName, actionExpression, ast);
|
directiveBinderBuilder.bindHostAction(actionName, actionExpression, ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindHostProperty(hostPropertyName, directivePropertyName, compileElement, directiveBinderBuilder) {
|
_bindHostProperty(hostPropertyName, directivePropertyName, compileElement,
|
||||||
|
directiveBinderBuilder) {
|
||||||
var ast = this._parser.parseBinding(directivePropertyName,
|
var ast = this._parser.parseBinding(directivePropertyName,
|
||||||
`hostProperties of ${compileElement.elementDescription}`);
|
`hostProperties of ${compileElement.elementDescription}`);
|
||||||
directiveBinderBuilder.bindHostProperty(hostPropertyName, ast);
|
directiveBinderBuilder.bindHostProperty(hostPropertyName, ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
_addHostAttribute(attrName, attrValue, compileElement) {
|
_addHostAttribute(attrName, attrValue, compileElement) {
|
||||||
if (StringWrapper.equals(attrName, 'class')) {
|
if (StringWrapper.equals(attrName, 'class')) {
|
||||||
ListWrapper.forEach(attrValue.split(' '), (className) => {
|
ListWrapper.forEach(attrValue.split(' '),
|
||||||
DOM.addClass(compileElement.element, className);
|
(className) => { DOM.addClass(compileElement.element, className); });
|
||||||
});
|
|
||||||
} else if (!DOM.hasAttribute(compileElement.element, attrName)) {
|
} else if (!DOM.hasAttribute(compileElement.element, attrName)) {
|
||||||
DOM.setAttribute(compileElement.element, attrName, attrValue);
|
DOM.setAttribute(compileElement.element, attrName, attrValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_splitBindConfig(bindConfig:string) {
|
_splitBindConfig(bindConfig: string) {
|
||||||
return ListWrapper.map(bindConfig.split('|'), (s) => s.trim());
|
return ListWrapper.map(bindConfig.split('|'), (s) => s.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,92 +22,82 @@ var BIND_NAME_REGEXP = RegExpWrapper.create(
|
|||||||
/**
|
/**
|
||||||
* Parses the property bindings on a single element.
|
* Parses the property bindings on a single element.
|
||||||
*/
|
*/
|
||||||
export class PropertyBindingParser extends CompileStep {
|
export class PropertyBindingParser implements CompileStep {
|
||||||
_parser:Parser;
|
_parser: Parser;
|
||||||
|
|
||||||
constructor(parser:Parser) {
|
constructor(parser: Parser) { this._parser = parser; }
|
||||||
super();
|
|
||||||
this._parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
var attrs = current.attrs();
|
var attrs = current.attrs();
|
||||||
var newAttrs = MapWrapper.create();
|
var newAttrs = MapWrapper.create();
|
||||||
|
|
||||||
MapWrapper.forEach(attrs, (attrValue, attrName) => {
|
MapWrapper.forEach(attrs, (attrValue, attrName) => {
|
||||||
var bindParts = RegExpWrapper.firstMatch(BIND_NAME_REGEXP, attrName);
|
var bindParts = RegExpWrapper.firstMatch(BIND_NAME_REGEXP, attrName);
|
||||||
if (isPresent(bindParts)) {
|
if (isPresent(bindParts)) {
|
||||||
if (isPresent(bindParts[1])) { // match: bind-prop
|
if (isPresent(bindParts[1])) { // match: bind-prop
|
||||||
this._bindProperty(bindParts[5], attrValue, current, newAttrs);
|
this._bindProperty(bindParts[5], attrValue, current, newAttrs);
|
||||||
|
|
||||||
} else if (isPresent(bindParts[2])) { // match: var-name / var-name="iden" / #name / #name="iden"
|
} else if (isPresent(
|
||||||
|
bindParts[2])) { // match: var-name / var-name="iden" / #name / #name="iden"
|
||||||
var identifier = bindParts[5];
|
var identifier = bindParts[5];
|
||||||
var value = attrValue == '' ? '\$implicit' : attrValue;
|
var value = attrValue == '' ? '\$implicit' : attrValue;
|
||||||
this._bindVariable(identifier, value, current, newAttrs);
|
this._bindVariable(identifier, value, current, newAttrs);
|
||||||
|
|
||||||
} else if (isPresent(bindParts[3])) { // match: on-event
|
} else if (isPresent(bindParts[3])) { // match: on-event
|
||||||
this._bindEvent(bindParts[5], attrValue, current, newAttrs);
|
this._bindEvent(bindParts[5], attrValue, current, newAttrs);
|
||||||
|
|
||||||
} else if (isPresent(bindParts[4])) { // match: bindon-prop
|
} else if (isPresent(bindParts[4])) { // match: bindon-prop
|
||||||
this._bindProperty(bindParts[5], attrValue, current, newAttrs);
|
this._bindProperty(bindParts[5], attrValue, current, newAttrs);
|
||||||
this._bindAssignmentEvent(bindParts[5], attrValue, current, newAttrs);
|
this._bindAssignmentEvent(bindParts[5], attrValue, current, newAttrs);
|
||||||
|
|
||||||
} else if (isPresent(bindParts[6])) { // match: [(expr)]
|
} else if (isPresent(bindParts[6])) { // match: [(expr)]
|
||||||
this._bindProperty(bindParts[6], attrValue, current, newAttrs);
|
this._bindProperty(bindParts[6], attrValue, current, newAttrs);
|
||||||
this._bindAssignmentEvent(bindParts[6], attrValue, current, newAttrs);
|
this._bindAssignmentEvent(bindParts[6], attrValue, current, newAttrs);
|
||||||
|
|
||||||
} else if (isPresent(bindParts[7])) { // match: [expr]
|
} else if (isPresent(bindParts[7])) { // match: [expr]
|
||||||
this._bindProperty(bindParts[7], attrValue, current, newAttrs);
|
this._bindProperty(bindParts[7], attrValue, current, newAttrs);
|
||||||
|
|
||||||
} else if (isPresent(bindParts[8])) { // match: (event)
|
} else if (isPresent(bindParts[8])) { // match: (event)
|
||||||
this._bindEvent(bindParts[8], attrValue, current, newAttrs);
|
this._bindEvent(bindParts[8], attrValue, current, newAttrs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var expr = this._parser.parseInterpolation(
|
var expr = this._parser.parseInterpolation(attrValue, current.elementDescription);
|
||||||
attrValue, current.elementDescription
|
|
||||||
);
|
|
||||||
if (isPresent(expr)) {
|
if (isPresent(expr)) {
|
||||||
this._bindPropertyAst(attrName, expr, current, newAttrs);
|
this._bindPropertyAst(attrName, expr, current, newAttrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
MapWrapper.forEach(newAttrs, (attrValue, attrName) => {
|
MapWrapper.forEach(newAttrs,
|
||||||
MapWrapper.set(attrs, attrName, attrValue);
|
(attrValue, attrName) => { MapWrapper.set(attrs, attrName, attrValue); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindVariable(identifier, value, current:CompileElement, newAttrs) {
|
_bindVariable(identifier, value, current: CompileElement, newAttrs) {
|
||||||
current.bindElement().bindVariable(dashCaseToCamelCase(identifier), value);
|
current.bindElement().bindVariable(dashCaseToCamelCase(identifier), value);
|
||||||
MapWrapper.set(newAttrs, identifier, value);
|
MapWrapper.set(newAttrs, identifier, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindProperty(name, expression, current:CompileElement, newAttrs) {
|
_bindProperty(name, expression, current: CompileElement, newAttrs) {
|
||||||
this._bindPropertyAst(
|
this._bindPropertyAst(name, this._parser.parseBinding(expression, current.elementDescription),
|
||||||
name,
|
current, newAttrs);
|
||||||
this._parser.parseBinding(expression, current.elementDescription),
|
|
||||||
current,
|
|
||||||
newAttrs
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindPropertyAst(name, ast, current:CompileElement, newAttrs) {
|
_bindPropertyAst(name, ast, current: CompileElement, newAttrs) {
|
||||||
var binder = current.bindElement();
|
var binder = current.bindElement();
|
||||||
var camelCaseName = dashCaseToCamelCase(name);
|
var camelCaseName = dashCaseToCamelCase(name);
|
||||||
binder.bindProperty(camelCaseName, ast);
|
binder.bindProperty(camelCaseName, ast);
|
||||||
MapWrapper.set(newAttrs, name, ast.source);
|
MapWrapper.set(newAttrs, name, ast.source);
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindAssignmentEvent(name, expression, current:CompileElement, newAttrs) {
|
_bindAssignmentEvent(name, expression, current: CompileElement, newAttrs) {
|
||||||
this._bindEvent(name, `${expression}=$event`, current, newAttrs);
|
this._bindEvent(name, `${expression}=$event`, current, newAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindEvent(name, expression, current:CompileElement, newAttrs) {
|
_bindEvent(name, expression, current: CompileElement, newAttrs) {
|
||||||
current.bindElement().bindEvent(
|
current.bindElement().bindEvent(
|
||||||
dashCaseToCamelCase(name), this._parser.parseAction(expression, current.elementDescription)
|
dashCaseToCamelCase(name),
|
||||||
);
|
this._parser.parseAction(expression, current.elementDescription));
|
||||||
// Don't detect directives for event names for now,
|
// Don't detect directives for event names for now,
|
||||||
// so don't add the event name to the CompileElement.attrs
|
// so don't add the event name to the CompileElement.attrs
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,17 +1,24 @@
|
|||||||
import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {isPresent, isBlank, RegExpWrapper, RegExpMatcherWrapper, StringWrapper, BaseException} from 'angular2/src/facade/lang';
|
import {
|
||||||
|
isPresent,
|
||||||
|
isBlank,
|
||||||
|
RegExpWrapper,
|
||||||
|
RegExpMatcherWrapper,
|
||||||
|
StringWrapper,
|
||||||
|
BaseException
|
||||||
|
} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
const _EMPTY_ATTR_VALUE = '';
|
const _EMPTY_ATTR_VALUE = '';
|
||||||
|
|
||||||
// TODO: Can't use `const` here as
|
// TODO: Can't use `const` here as
|
||||||
// in Dart this is not transpiled into `final` yet...
|
// in Dart this is not transpiled into `final` yet...
|
||||||
var _SELECTOR_REGEXP =
|
var _SELECTOR_REGEXP = RegExpWrapper.create(
|
||||||
RegExpWrapper.create('(\\:not\\()|' + //":not("
|
'(\\:not\\()|' + //":not("
|
||||||
'([-\\w]+)|' + // "tag"
|
'([-\\w]+)|' + // "tag"
|
||||||
'(?:\\.([-\\w]+))|' + // ".class"
|
'(?:\\.([-\\w]+))|' + // ".class"
|
||||||
'(?:\\[([-\\w*]+)(?:=([^\\]]*))?\\])|' + // "[name]", "[name=value]" or "[name*=value]"
|
'(?:\\[([-\\w*]+)(?:=([^\\]]*))?\\])|' + // "[name]", "[name=value]" or "[name*=value]"
|
||||||
'(?:\\))|' + // ")"
|
'(?:\\))|' + // ")"
|
||||||
'(\\s*,\\s*)'); // ","
|
'(\\s*,\\s*)'); // ","
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A css selector contains an element name,
|
* A css selector contains an element name,
|
||||||
@ -19,110 +26,107 @@ var _SELECTOR_REGEXP =
|
|||||||
* of selecting subsets out of them.
|
* of selecting subsets out of them.
|
||||||
*/
|
*/
|
||||||
export class CssSelector {
|
export class CssSelector {
|
||||||
element:string;
|
element: string;
|
||||||
classNames:List;
|
classNames: List<string>;
|
||||||
attrs:List;
|
attrs: List<string>;
|
||||||
notSelector: CssSelector;
|
notSelector: CssSelector;
|
||||||
static parse(selector:string): List<CssSelector> {
|
static parse(selector: string): List<CssSelector> {
|
||||||
var results = ListWrapper.create();
|
var results = ListWrapper.create();
|
||||||
var _addResult = (res, cssSel) => {
|
var _addResult = (res, cssSel) => {
|
||||||
if (isPresent(cssSel.notSelector) && isBlank(cssSel.element)
|
if (isPresent(cssSel.notSelector) && isBlank(cssSel.element) &&
|
||||||
&& ListWrapper.isEmpty(cssSel.classNames) && ListWrapper.isEmpty(cssSel.attrs)) {
|
ListWrapper.isEmpty(cssSel.classNames) && ListWrapper.isEmpty(cssSel.attrs)) {
|
||||||
cssSel.element = "*";
|
cssSel.element = "*";
|
||||||
}
|
} ListWrapper.push(res, cssSel);
|
||||||
ListWrapper.push(res, cssSel);
|
|
||||||
}
|
|
||||||
var cssSelector = new CssSelector();
|
|
||||||
var matcher = RegExpWrapper.matcher(_SELECTOR_REGEXP, selector);
|
|
||||||
var match;
|
|
||||||
var current = cssSelector;
|
|
||||||
while (isPresent(match = RegExpMatcherWrapper.next(matcher))) {
|
|
||||||
if (isPresent(match[1])) {
|
|
||||||
if (isPresent(cssSelector.notSelector)) {
|
|
||||||
throw new BaseException('Nesting :not is not allowed in a selector');
|
|
||||||
}
|
|
||||||
current.notSelector = new CssSelector();
|
|
||||||
current = current.notSelector;
|
|
||||||
}
|
|
||||||
if (isPresent(match[2])) {
|
|
||||||
current.setElement(match[2]);
|
|
||||||
}
|
|
||||||
if (isPresent(match[3])) {
|
|
||||||
current.addClassName(match[3]);
|
|
||||||
}
|
|
||||||
if (isPresent(match[4])) {
|
|
||||||
current.addAttribute(match[4], match[5]);
|
|
||||||
}
|
|
||||||
if (isPresent(match[6])) {
|
|
||||||
_addResult(results, cssSelector);
|
|
||||||
cssSelector = current = new CssSelector();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_addResult(results, cssSelector);
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
var cssSelector = new CssSelector();
|
||||||
|
var matcher = RegExpWrapper.matcher(_SELECTOR_REGEXP, selector);
|
||||||
|
var match;
|
||||||
|
var current = cssSelector;
|
||||||
|
while (isPresent(match = RegExpMatcherWrapper.next(matcher))) {
|
||||||
|
if (isPresent(match[1])) {
|
||||||
|
if (isPresent(cssSelector.notSelector)) {
|
||||||
|
throw new BaseException('Nesting :not is not allowed in a selector');
|
||||||
|
}
|
||||||
|
current.notSelector = new CssSelector();
|
||||||
|
current = current.notSelector;
|
||||||
|
}
|
||||||
|
if (isPresent(match[2])) {
|
||||||
|
current.setElement(match[2]);
|
||||||
|
}
|
||||||
|
if (isPresent(match[3])) {
|
||||||
|
current.addClassName(match[3]);
|
||||||
|
}
|
||||||
|
if (isPresent(match[4])) {
|
||||||
|
current.addAttribute(match[4], match[5]);
|
||||||
|
}
|
||||||
|
if (isPresent(match[6])) {
|
||||||
|
_addResult(results, cssSelector);
|
||||||
|
cssSelector = current = new CssSelector();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_addResult(results, cssSelector);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.element = null;
|
this.element = null;
|
||||||
this.classNames = ListWrapper.create();
|
this.classNames = ListWrapper.create();
|
||||||
this.attrs = ListWrapper.create();
|
this.attrs = ListWrapper.create();
|
||||||
this.notSelector = null;
|
this.notSelector = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isElementSelector():boolean {
|
isElementSelector(): boolean {
|
||||||
return isPresent(this.element) &&
|
return isPresent(this.element) && ListWrapper.isEmpty(this.classNames) &&
|
||||||
ListWrapper.isEmpty(this.classNames) &&
|
ListWrapper.isEmpty(this.attrs) && isBlank(this.notSelector);
|
||||||
ListWrapper.isEmpty(this.attrs) &&
|
}
|
||||||
isBlank(this.notSelector);
|
|
||||||
}
|
|
||||||
|
|
||||||
setElement(element:string = null) {
|
setElement(element: string = null) {
|
||||||
if (isPresent(element)) {
|
if (isPresent(element)) {
|
||||||
element = element.toLowerCase();
|
element = element.toLowerCase();
|
||||||
|
}
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
addAttribute(name: string, value: string = _EMPTY_ATTR_VALUE) {
|
||||||
|
ListWrapper.push(this.attrs, name.toLowerCase());
|
||||||
|
if (isPresent(value)) {
|
||||||
|
value = value.toLowerCase();
|
||||||
|
} else {
|
||||||
|
value = _EMPTY_ATTR_VALUE;
|
||||||
|
}
|
||||||
|
ListWrapper.push(this.attrs, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
addClassName(name: string) {
|
||||||
|
ListWrapper.push(this.classNames, name.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(): string {
|
||||||
|
var res = '';
|
||||||
|
if (isPresent(this.element)) {
|
||||||
|
res += this.element;
|
||||||
|
}
|
||||||
|
if (isPresent(this.classNames)) {
|
||||||
|
for (var i = 0; i < this.classNames.length; i++) {
|
||||||
|
res += '.' + this.classNames[i];
|
||||||
}
|
}
|
||||||
this.element = element;
|
|
||||||
}
|
}
|
||||||
|
if (isPresent(this.attrs)) {
|
||||||
addAttribute(name:string, value:string = _EMPTY_ATTR_VALUE) {
|
for (var i = 0; i < this.attrs.length;) {
|
||||||
ListWrapper.push(this.attrs, name.toLowerCase());
|
var attrName = this.attrs[i++];
|
||||||
if (isPresent(value)) {
|
var attrValue = this.attrs[i++];
|
||||||
value = value.toLowerCase();
|
res += '[' + attrName;
|
||||||
} else {
|
if (attrValue.length > 0) {
|
||||||
value = _EMPTY_ATTR_VALUE;
|
res += '=' + attrValue;
|
||||||
}
|
|
||||||
ListWrapper.push(this.attrs, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
addClassName(name:string) {
|
|
||||||
ListWrapper.push(this.classNames, name.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
toString():string {
|
|
||||||
var res = '';
|
|
||||||
if (isPresent(this.element)) {
|
|
||||||
res += this.element;
|
|
||||||
}
|
|
||||||
if (isPresent(this.classNames)) {
|
|
||||||
for (var i=0; i<this.classNames.length; i++) {
|
|
||||||
res += '.' + this.classNames[i];
|
|
||||||
}
|
}
|
||||||
|
res += ']';
|
||||||
}
|
}
|
||||||
if (isPresent(this.attrs)) {
|
|
||||||
for (var i=0; i<this.attrs.length;) {
|
|
||||||
var attrName = this.attrs[i++];
|
|
||||||
var attrValue = this.attrs[i++]
|
|
||||||
res += '[' + attrName;
|
|
||||||
if (attrValue.length > 0) {
|
|
||||||
res += '=' + attrValue;
|
|
||||||
}
|
|
||||||
res += ']';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isPresent(this.notSelector)) {
|
|
||||||
res += ":not(" + this.notSelector.toString() + ")";
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
if (isPresent(this.notSelector)) {
|
||||||
|
res += ":not(" + this.notSelector.toString() + ")";
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,13 +134,20 @@ export class CssSelector {
|
|||||||
* are contained in a given CssSelector.
|
* are contained in a given CssSelector.
|
||||||
*/
|
*/
|
||||||
export class SelectorMatcher {
|
export class SelectorMatcher {
|
||||||
_elementMap:Map;
|
static createNotMatcher(notSelector:CssSelector) {
|
||||||
_elementPartialMap:Map;
|
var notMatcher = new SelectorMatcher();
|
||||||
_classMap:Map;
|
notMatcher._addSelectable(notSelector, null, null);
|
||||||
_classPartialMap:Map;
|
return notMatcher;
|
||||||
_attrValueMap:Map;
|
}
|
||||||
_attrValuePartialMap:Map;
|
|
||||||
_listContexts:List;
|
private _elementMap: Map<string, string>;
|
||||||
|
private _elementPartialMap: Map<string, string>;
|
||||||
|
private _classMap: Map<string, string>;
|
||||||
|
private _classPartialMap: Map<string, string>;
|
||||||
|
private _attrValueMap: Map<string, string>;
|
||||||
|
private _attrValuePartialMap: Map<string, string>;
|
||||||
|
private _listContexts: List<SelectorListContext>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._elementMap = MapWrapper.create();
|
this._elementMap = MapWrapper.create();
|
||||||
this._elementPartialMap = MapWrapper.create();
|
this._elementPartialMap = MapWrapper.create();
|
||||||
@ -150,14 +161,14 @@ export class SelectorMatcher {
|
|||||||
this._listContexts = ListWrapper.create();
|
this._listContexts = ListWrapper.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
addSelectables(cssSelectors:List<CssSelector>, callbackCtxt) {
|
addSelectables(cssSelectors: List<CssSelector>, callbackCtxt: any) {
|
||||||
var listContext = null;
|
var listContext = null;
|
||||||
if (cssSelectors.length > 1) {
|
if (cssSelectors.length > 1) {
|
||||||
listContext= new SelectorListContext(cssSelectors);
|
listContext = new SelectorListContext(cssSelectors);
|
||||||
ListWrapper.push(this._listContexts, listContext);
|
ListWrapper.push(this._listContexts, listContext);
|
||||||
}
|
}
|
||||||
for (var i = 0; i < cssSelectors.length; i++) {
|
for (var i = 0; i < cssSelectors.length; i++) {
|
||||||
this.addSelectable(cssSelectors[i], callbackCtxt, listContext);
|
this._addSelectable(cssSelectors[i], callbackCtxt, listContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +177,7 @@ export class SelectorMatcher {
|
|||||||
* @param cssSelector A css selector
|
* @param cssSelector A css selector
|
||||||
* @param callbackCtxt An opaque object that will be given to the callback of the `match` function
|
* @param callbackCtxt An opaque object that will be given to the callback of the `match` function
|
||||||
*/
|
*/
|
||||||
addSelectable(cssSelector, callbackCtxt, listContext: SelectorListContext) {
|
private _addSelectable(cssSelector: CssSelector, callbackCtxt: any, listContext: SelectorListContext) {
|
||||||
var matcher = this;
|
var matcher = this;
|
||||||
var element = cssSelector.element;
|
var element = cssSelector.element;
|
||||||
var classNames = cssSelector.classNames;
|
var classNames = cssSelector.classNames;
|
||||||
@ -184,7 +195,7 @@ export class SelectorMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(classNames)) {
|
if (isPresent(classNames)) {
|
||||||
for (var index = 0; index<classNames.length; index++) {
|
for (var index = 0; index < classNames.length; index++) {
|
||||||
var isTerminal = attrs.length === 0 && index === classNames.length - 1;
|
var isTerminal = attrs.length === 0 && index === classNames.length - 1;
|
||||||
var className = classNames[index];
|
var className = classNames[index];
|
||||||
if (isTerminal) {
|
if (isTerminal) {
|
||||||
@ -196,12 +207,12 @@ export class SelectorMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(attrs)) {
|
if (isPresent(attrs)) {
|
||||||
for (var index = 0; index<attrs.length; ) {
|
for (var index = 0; index < attrs.length;) {
|
||||||
var isTerminal = index === attrs.length - 2;
|
var isTerminal = index === attrs.length - 2;
|
||||||
var attrName = attrs[index++];
|
var attrName = attrs[index++];
|
||||||
var attrValue = attrs[index++];
|
var attrValue = attrs[index++];
|
||||||
var map = isTerminal ? matcher._attrValueMap : matcher._attrValuePartialMap;
|
var map = isTerminal ? matcher._attrValueMap : matcher._attrValuePartialMap;
|
||||||
var valuesMap = MapWrapper.get(map, attrName)
|
var valuesMap = MapWrapper.get(map, attrName);
|
||||||
if (isBlank(valuesMap)) {
|
if (isBlank(valuesMap)) {
|
||||||
valuesMap = MapWrapper.create();
|
valuesMap = MapWrapper.create();
|
||||||
MapWrapper.set(map, attrName, valuesMap);
|
MapWrapper.set(map, attrName, valuesMap);
|
||||||
@ -215,8 +226,8 @@ export class SelectorMatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_addTerminal(map:Map<string,string>, name:string, selectable) {
|
private _addTerminal(map: Map<string, string>, name: string, selectable: SelectorContext) {
|
||||||
var terminalList = MapWrapper.get(map, name)
|
var terminalList = MapWrapper.get(map, name);
|
||||||
if (isBlank(terminalList)) {
|
if (isBlank(terminalList)) {
|
||||||
terminalList = ListWrapper.create();
|
terminalList = ListWrapper.create();
|
||||||
MapWrapper.set(map, name, terminalList);
|
MapWrapper.set(map, name, terminalList);
|
||||||
@ -224,8 +235,8 @@ export class SelectorMatcher {
|
|||||||
ListWrapper.push(terminalList, selectable);
|
ListWrapper.push(terminalList, selectable);
|
||||||
}
|
}
|
||||||
|
|
||||||
_addPartial(map:Map<string,string>, name:string) {
|
private _addPartial(map: Map<string, string>, name: string) {
|
||||||
var matcher = MapWrapper.get(map, name)
|
var matcher = MapWrapper.get(map, name);
|
||||||
if (isBlank(matcher)) {
|
if (isBlank(matcher)) {
|
||||||
matcher = new SelectorMatcher();
|
matcher = new SelectorMatcher();
|
||||||
MapWrapper.set(map, name, matcher);
|
MapWrapper.set(map, name, matcher);
|
||||||
@ -240,7 +251,7 @@ export class SelectorMatcher {
|
|||||||
* @param matchedCallback This callback will be called with the object handed into `addSelectable`
|
* @param matchedCallback This callback will be called with the object handed into `addSelectable`
|
||||||
* @return boolean true if a match was found
|
* @return boolean true if a match was found
|
||||||
*/
|
*/
|
||||||
match(cssSelector:CssSelector, matchedCallback:Function):boolean {
|
match(cssSelector: CssSelector, matchedCallback /*: (CssSelector, any) => void*/): boolean {
|
||||||
var result = false;
|
var result = false;
|
||||||
var element = cssSelector.element;
|
var element = cssSelector.element;
|
||||||
var classNames = cssSelector.classNames;
|
var classNames = cssSelector.classNames;
|
||||||
@ -251,35 +262,42 @@ export class SelectorMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;
|
result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;
|
||||||
result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) || result;
|
result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) ||
|
||||||
|
result;
|
||||||
|
|
||||||
if (isPresent(classNames)) {
|
if (isPresent(classNames)) {
|
||||||
for (var index = 0; index<classNames.length; index++) {
|
for (var index = 0; index < classNames.length; index++) {
|
||||||
var className = classNames[index];
|
var className = classNames[index];
|
||||||
result = this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result;
|
result =
|
||||||
result = this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) || result;
|
this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result;
|
||||||
|
result =
|
||||||
|
this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) ||
|
||||||
|
result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(attrs)) {
|
if (isPresent(attrs)) {
|
||||||
for (var index = 0; index<attrs.length;) {
|
for (var index = 0; index < attrs.length;) {
|
||||||
var attrName = attrs[index++];
|
var attrName = attrs[index++];
|
||||||
var attrValue = attrs[index++];
|
var attrValue = attrs[index++];
|
||||||
|
|
||||||
var valuesMap = MapWrapper.get(this._attrValueMap, attrName);
|
var valuesMap = MapWrapper.get(this._attrValueMap, attrName);
|
||||||
if (!StringWrapper.equals(attrValue, _EMPTY_ATTR_VALUE)) {
|
if (!StringWrapper.equals(attrValue, _EMPTY_ATTR_VALUE)) {
|
||||||
result = this._matchTerminal(valuesMap, _EMPTY_ATTR_VALUE, cssSelector, matchedCallback) || result;
|
result =
|
||||||
|
this._matchTerminal(valuesMap, _EMPTY_ATTR_VALUE, cssSelector, matchedCallback) ||
|
||||||
|
result;
|
||||||
}
|
}
|
||||||
result = this._matchTerminal(valuesMap, attrValue, cssSelector, matchedCallback) || result;
|
result = this._matchTerminal(valuesMap, attrValue, cssSelector, matchedCallback) || result;
|
||||||
|
|
||||||
valuesMap = MapWrapper.get(this._attrValuePartialMap, attrName)
|
valuesMap = MapWrapper.get(this._attrValuePartialMap, attrName);
|
||||||
result = this._matchPartial(valuesMap, attrValue, cssSelector, matchedCallback) || result;
|
result = this._matchPartial(valuesMap, attrValue, cssSelector, matchedCallback) || result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
_matchTerminal(map:Map<string,string> = null, name, cssSelector, matchedCallback):boolean {
|
_matchTerminal(map: Map<string, string>, name, cssSelector: CssSelector,
|
||||||
|
matchedCallback /*: (CssSelector, any) => void*/): boolean {
|
||||||
if (isBlank(map) || isBlank(name)) {
|
if (isBlank(map) || isBlank(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -294,18 +312,19 @@ export class SelectorMatcher {
|
|||||||
}
|
}
|
||||||
var selectable;
|
var selectable;
|
||||||
var result = false;
|
var result = false;
|
||||||
for (var index=0; index<selectables.length; index++) {
|
for (var index = 0; index < selectables.length; index++) {
|
||||||
selectable = selectables[index];
|
selectable = selectables[index];
|
||||||
result = selectable.finalize(cssSelector, matchedCallback) || result;
|
result = selectable.finalize(cssSelector, matchedCallback) || result;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
_matchPartial(map:Map<string,string> = null, name, cssSelector, matchedCallback):boolean {
|
_matchPartial(map: Map<string, string>, name, cssSelector: CssSelector,
|
||||||
|
matchedCallback /*: (CssSelector, any) => void*/): boolean {
|
||||||
if (isBlank(map) || isBlank(name)) {
|
if (isBlank(map) || isBlank(name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var nestedSelector = MapWrapper.get(map, name)
|
var nestedSelector = MapWrapper.get(map, name);
|
||||||
if (isBlank(nestedSelector)) {
|
if (isBlank(nestedSelector)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -321,7 +340,7 @@ class SelectorListContext {
|
|||||||
selectors: List<CssSelector>;
|
selectors: List<CssSelector>;
|
||||||
alreadyMatched: boolean;
|
alreadyMatched: boolean;
|
||||||
|
|
||||||
constructor(selectors:List<CssSelector>) {
|
constructor(selectors: List<CssSelector>) {
|
||||||
this.selectors = selectors;
|
this.selectors = selectors;
|
||||||
this.alreadyMatched = false;
|
this.alreadyMatched = false;
|
||||||
}
|
}
|
||||||
@ -329,26 +348,27 @@ class SelectorListContext {
|
|||||||
|
|
||||||
// Store context to pass back selector and context when a selector is matched
|
// Store context to pass back selector and context when a selector is matched
|
||||||
class SelectorContext {
|
class SelectorContext {
|
||||||
selector:CssSelector;
|
selector: CssSelector;
|
||||||
notSelector:CssSelector;
|
notSelector: CssSelector;
|
||||||
cbContext; // callback context
|
cbContext; // callback context
|
||||||
listContext: SelectorListContext;
|
listContext: SelectorListContext;
|
||||||
|
|
||||||
constructor(selector:CssSelector, cbContext, listContext: SelectorListContext) {
|
constructor(selector: CssSelector, cbContext: any, listContext: SelectorListContext) {
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.notSelector = selector.notSelector;
|
this.notSelector = selector.notSelector;
|
||||||
this.cbContext = cbContext;
|
this.cbContext = cbContext;
|
||||||
this.listContext = listContext;
|
this.listContext = listContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize(cssSelector: CssSelector, callback) {
|
finalize(cssSelector: CssSelector, callback /*: (CssSelector, any) => void*/) {
|
||||||
var result = true;
|
var result = true;
|
||||||
if (isPresent(this.notSelector) && (isBlank(this.listContext) || !this.listContext.alreadyMatched)) {
|
if (isPresent(this.notSelector) &&
|
||||||
var notMatcher = new SelectorMatcher();
|
(isBlank(this.listContext) || !this.listContext.alreadyMatched)) {
|
||||||
notMatcher.addSelectable(this.notSelector, null, null);
|
var notMatcher = SelectorMatcher.createNotMatcher(this.notSelector);
|
||||||
result = !notMatcher.match(cssSelector, null);
|
result = !notMatcher.match(cssSelector, null);
|
||||||
}
|
}
|
||||||
if (result && isPresent(callback) && (isBlank(this.listContext) || !this.listContext.alreadyMatched)) {
|
if (result && isPresent(callback) &&
|
||||||
|
(isBlank(this.listContext) || !this.listContext.alreadyMatched)) {
|
||||||
if (isPresent(this.listContext)) {
|
if (isPresent(this.listContext)) {
|
||||||
this.listContext.alreadyMatched = true;
|
this.listContext.alreadyMatched = true;
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
import {Injectable} from 'angular2/di';
|
||||||
import {isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
|
||||||
import {Map, MapWrapper, StringMapWrapper, StringMap} from 'angular2/src/facade/collection';
|
import {Map, MapWrapper, StringMapWrapper, StringMap} from 'angular2/src/facade/collection';
|
||||||
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
import {PromiseWrapper, Promise} from 'angular2/src/facade/async';
|
||||||
@ -16,14 +16,14 @@ import {UrlResolver} from 'angular2/src/services/url_resolver';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class TemplateLoader {
|
export class TemplateLoader {
|
||||||
_xhr: XHR;
|
_xhr: XHR;
|
||||||
_htmlCache: StringMap;
|
_htmlCache: StringMap<string, /*element*/ any>;
|
||||||
|
|
||||||
constructor(xhr: XHR, urlResolver: UrlResolver) {
|
constructor(xhr: XHR, urlResolver: UrlResolver) {
|
||||||
this._xhr = xhr;
|
this._xhr = xhr;
|
||||||
this._htmlCache = StringMapWrapper.create();
|
this._htmlCache = StringMapWrapper.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
load(template: ViewDefinition):Promise {
|
load(template: ViewDefinition): Promise</*element*/ any> {
|
||||||
if (isPresent(template.template)) {
|
if (isPresent(template.template)) {
|
||||||
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
return PromiseWrapper.resolve(DOM.createTemplate(template.template));
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ export class TemplateLoader {
|
|||||||
var promise = StringMapWrapper.get(this._htmlCache, url);
|
var promise = StringMapWrapper.get(this._htmlCache, url);
|
||||||
|
|
||||||
if (isBlank(promise)) {
|
if (isBlank(promise)) {
|
||||||
promise = this._xhr.get(url).then(function (html) {
|
promise = this._xhr.get(url).then(function(html) {
|
||||||
var template = DOM.createTemplate(html);
|
var template = DOM.createTemplate(html);
|
||||||
return template;
|
return template;
|
||||||
});
|
});
|
||||||
@ -41,7 +41,7 @@ export class TemplateLoader {
|
|||||||
|
|
||||||
// We need to clone the result as others might change it
|
// We need to clone the result as others might change it
|
||||||
// (e.g. the compiler).
|
// (e.g. the compiler).
|
||||||
return promise.then( (tplElement) => DOM.clone(tplElement) );
|
return promise.then((tplElement) => DOM.clone(tplElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new BaseException('View should have either the url or template property set');
|
throw new BaseException('View should have either the url or template property set');
|
@ -10,21 +10,18 @@ import {CompileControl} from './compile_control';
|
|||||||
/**
|
/**
|
||||||
* Parses interpolations in direct text child nodes of the current element.
|
* Parses interpolations in direct text child nodes of the current element.
|
||||||
*/
|
*/
|
||||||
export class TextInterpolationParser extends CompileStep {
|
export class TextInterpolationParser implements CompileStep {
|
||||||
_parser:Parser;
|
_parser: Parser;
|
||||||
|
|
||||||
constructor(parser:Parser) {
|
constructor(parser: Parser) { this._parser = parser; }
|
||||||
super();
|
|
||||||
this._parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
if (!current.compileChildren) {
|
if (!current.compileChildren) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var element = current.element;
|
var element = current.element;
|
||||||
var childNodes = DOM.childNodes(DOM.templateAwareRoot(element));
|
var childNodes = DOM.childNodes(DOM.templateAwareRoot(element));
|
||||||
for (var i=0; i<childNodes.length; i++) {
|
for (var i = 0; i < childNodes.length; i++) {
|
||||||
var node = childNodes[i];
|
var node = childNodes[i];
|
||||||
if (DOM.isTextNode(node)) {
|
if (DOM.isTextNode(node)) {
|
||||||
var text = DOM.nodeValue(node);
|
var text = DOM.nodeValue(node);
|
@ -25,28 +25,26 @@ import {dashCaseToCamelCase} from '../util';
|
|||||||
* as we want to do locate elements with bindings using `getElementsByClassName` later on,
|
* as we want to do locate elements with bindings using `getElementsByClassName` later on,
|
||||||
* which should not descend into the nested view.
|
* which should not descend into the nested view.
|
||||||
*/
|
*/
|
||||||
export class ViewSplitter extends CompileStep {
|
export class ViewSplitter implements CompileStep {
|
||||||
_parser:Parser;
|
_parser: Parser;
|
||||||
|
|
||||||
constructor(parser:Parser) {
|
constructor(parser: Parser) { this._parser = parser; }
|
||||||
super();
|
|
||||||
this._parser = parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
var attrs = current.attrs();
|
var attrs = current.attrs();
|
||||||
var templateBindings = MapWrapper.get(attrs, 'template');
|
var templateBindings = MapWrapper.get(attrs, 'template');
|
||||||
var hasTemplateBinding = isPresent(templateBindings);
|
var hasTemplateBinding = isPresent(templateBindings);
|
||||||
|
|
||||||
// look for template shortcuts such as *ng-if="condition" and treat them as template="if condition"
|
// look for template shortcuts such as *ng-if="condition" and treat them as template="if
|
||||||
|
// condition"
|
||||||
MapWrapper.forEach(attrs, (attrValue, attrName) => {
|
MapWrapper.forEach(attrs, (attrValue, attrName) => {
|
||||||
if (StringWrapper.startsWith(attrName, '*')) {
|
if (StringWrapper.startsWith(attrName, '*')) {
|
||||||
var key = StringWrapper.substring(attrName, 1); // remove the star
|
var key = StringWrapper.substring(attrName, 1); // remove the star
|
||||||
if (hasTemplateBinding) {
|
if (hasTemplateBinding) {
|
||||||
// 2nd template binding detected
|
// 2nd template binding detected
|
||||||
throw new BaseException(`Only one template directive per element is allowed: ` +
|
throw new BaseException(`Only one template directive per element is allowed: ` +
|
||||||
`${templateBindings} and ${key} cannot be used simultaneously ` +
|
`${templateBindings} and ${key} cannot be used simultaneously ` +
|
||||||
`in ${current.elementDescription}`);
|
`in ${current.elementDescription}`);
|
||||||
} else {
|
} else {
|
||||||
templateBindings = (attrValue.length == 0) ? key : key + ' ' + attrValue;
|
templateBindings = (attrValue.length == 0) ? key : key + ' ' + attrValue;
|
||||||
hasTemplateBinding = true;
|
hasTemplateBinding = true;
|
||||||
@ -67,7 +65,8 @@ export class ViewSplitter extends CompileStep {
|
|||||||
this._moveChildNodes(DOM.content(current.element), DOM.content(viewRoot.element));
|
this._moveChildNodes(DOM.content(current.element), DOM.content(viewRoot.element));
|
||||||
control.addChild(viewRoot);
|
control.addChild(viewRoot);
|
||||||
}
|
}
|
||||||
} if (hasTemplateBinding) {
|
}
|
||||||
|
if (hasTemplateBinding) {
|
||||||
var newParent = new CompileElement(DOM.createTemplate(''));
|
var newParent = new CompileElement(DOM.createTemplate(''));
|
||||||
newParent.inheritedProtoView = current.inheritedProtoView;
|
newParent.inheritedProtoView = current.inheritedProtoView;
|
||||||
newParent.inheritedElementBinder = current.inheritedElementBinder;
|
newParent.inheritedElementBinder = current.inheritedElementBinder;
|
||||||
@ -102,19 +101,17 @@ export class ViewSplitter extends CompileStep {
|
|||||||
DOM.appendChild(newParentElement, currentElement);
|
DOM.appendChild(newParentElement, currentElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
_parseTemplateBindings(templateBindings:string, compileElement:CompileElement) {
|
_parseTemplateBindings(templateBindings: string, compileElement: CompileElement) {
|
||||||
var bindings = this._parser.parseTemplateBindings(templateBindings, compileElement.elementDescription);
|
var bindings =
|
||||||
for (var i=0; i<bindings.length; i++) {
|
this._parser.parseTemplateBindings(templateBindings, compileElement.elementDescription);
|
||||||
|
for (var i = 0; i < bindings.length; i++) {
|
||||||
var binding = bindings[i];
|
var binding = bindings[i];
|
||||||
if (binding.keyIsVar) {
|
if (binding.keyIsVar) {
|
||||||
compileElement.bindElement().bindVariable(
|
compileElement.bindElement().bindVariable(dashCaseToCamelCase(binding.key), binding.name);
|
||||||
dashCaseToCamelCase(binding.key), binding.name
|
|
||||||
);
|
|
||||||
MapWrapper.set(compileElement.attrs(), binding.key, binding.name);
|
MapWrapper.set(compileElement.attrs(), binding.key, binding.name);
|
||||||
} else if (isPresent(binding.expression)) {
|
} else if (isPresent(binding.expression)) {
|
||||||
compileElement.bindElement().bindProperty(
|
compileElement.bindElement().bindProperty(dashCaseToCamelCase(binding.key),
|
||||||
dashCaseToCamelCase(binding.key), binding.expression
|
binding.expression);
|
||||||
);
|
|
||||||
MapWrapper.set(compileElement.attrs(), binding.key, binding.expression.source);
|
MapWrapper.set(compileElement.attrs(), binding.key, binding.expression.source);
|
||||||
} else {
|
} else {
|
||||||
DOM.setAttribute(compileElement.element, binding.key, '');
|
DOM.setAttribute(compileElement.element, binding.key, '');
|
@ -6,7 +6,7 @@ import {DirectiveMetadata} from 'angular2/src/render/api';
|
|||||||
* Converts a [DirectiveMetadata] to a map representation. This creates a copy,
|
* Converts a [DirectiveMetadata] to a map representation. This creates a copy,
|
||||||
* that is, subsequent changes to `meta` will not be mirrored in the map.
|
* that is, subsequent changes to `meta` will not be mirrored in the map.
|
||||||
*/
|
*/
|
||||||
export function directiveMetadataToMap(meta: DirectiveMetadata): Map {
|
export function directiveMetadataToMap(meta: DirectiveMetadata): Map<string, any> {
|
||||||
return MapWrapper.createFromPairs([
|
return MapWrapper.createFromPairs([
|
||||||
['id', meta.id],
|
['id', meta.id],
|
||||||
['selector', meta.selector],
|
['selector', meta.selector],
|
||||||
@ -27,18 +27,18 @@ export function directiveMetadataToMap(meta: DirectiveMetadata): Map {
|
|||||||
* [DirectiveMetadata] object. This creates a copy, that is, subsequent changes
|
* [DirectiveMetadata] object. This creates a copy, that is, subsequent changes
|
||||||
* to `map` will not be mirrored in the [DirectiveMetadata] object.
|
* to `map` will not be mirrored in the [DirectiveMetadata] object.
|
||||||
*/
|
*/
|
||||||
export function directiveMetadataFromMap(map: Map): DirectiveMetadata {
|
export function directiveMetadataFromMap(map: Map<string, any>): DirectiveMetadata {
|
||||||
return new DirectiveMetadata({
|
return new DirectiveMetadata({
|
||||||
id: MapWrapper.get(map, 'id'),
|
id:<string>MapWrapper.get(map, 'id'),
|
||||||
selector: MapWrapper.get(map, 'selector'),
|
selector:<string>MapWrapper.get(map, 'selector'),
|
||||||
compileChildren: MapWrapper.get(map, 'compileChildren'),
|
compileChildren:<boolean>MapWrapper.get(map, 'compileChildren'),
|
||||||
hostListeners: _cloneIfPresent(MapWrapper.get(map, 'hostListeners')),
|
hostListeners:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostListeners')),
|
||||||
hostProperties: _cloneIfPresent(MapWrapper.get(map, 'hostProperties')),
|
hostProperties:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostProperties')),
|
||||||
hostActions: _cloneIfPresent(MapWrapper.get(map, 'hostActions')),
|
hostActions:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostActions')),
|
||||||
hostAttributes: _cloneIfPresent(MapWrapper.get(map, 'hostAttributes')),
|
hostAttributes:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'hostAttributes')),
|
||||||
properties: _cloneIfPresent(MapWrapper.get(map, 'properties')),
|
properties:<Map<string, string>>_cloneIfPresent(MapWrapper.get(map, 'properties')),
|
||||||
readAttributes: _cloneIfPresent(MapWrapper.get(map, 'readAttributes')),
|
readAttributes:<List<string>>_cloneIfPresent(MapWrapper.get(map, 'readAttributes')),
|
||||||
type: MapWrapper.get(map, 'type')
|
type:<number>MapWrapper.get(map, 'type')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
import {Inject, Injectable} from 'angular2/src/di/annotations_impl';
|
import {Inject, Injectable} from 'angular2/di';
|
||||||
import {int, isPresent, isBlank, BaseException, RegExpWrapper} from 'angular2/src/facade/lang';
|
import {int, isPresent, isBlank, BaseException, RegExpWrapper} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper, MapWrapper, Map, StringMapWrapper, List} from 'angular2/src/facade/collection';
|
import {ListWrapper, MapWrapper, Map, StringMapWrapper, List} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
@ -21,18 +21,20 @@ export const DOCUMENT_TOKEN = 'DocumentToken';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DomRenderer extends Renderer {
|
export class DomRenderer extends Renderer {
|
||||||
_eventManager:EventManager;
|
_eventManager: EventManager;
|
||||||
_shadowDomStrategy:ShadowDomStrategy;
|
_shadowDomStrategy: ShadowDomStrategy;
|
||||||
_document;
|
_document;
|
||||||
|
|
||||||
constructor(eventManager:EventManager, shadowDomStrategy:ShadowDomStrategy, @Inject(DOCUMENT_TOKEN) document) {
|
constructor(eventManager: EventManager, shadowDomStrategy: ShadowDomStrategy,
|
||||||
|
@Inject(DOCUMENT_TOKEN) document) {
|
||||||
super();
|
super();
|
||||||
this._eventManager = eventManager;
|
this._eventManager = eventManager;
|
||||||
this._shadowDomStrategy = shadowDomStrategy;
|
this._shadowDomStrategy = shadowDomStrategy;
|
||||||
this._document = document;
|
this._document = document;
|
||||||
}
|
}
|
||||||
|
|
||||||
createRootHostView(hostProtoViewRef:RenderProtoViewRef, hostElementSelector:string):RenderViewRef {
|
createRootHostView(hostProtoViewRef: RenderProtoViewRef,
|
||||||
|
hostElementSelector: string): RenderViewRef {
|
||||||
var hostProtoView = resolveInternalDomProtoView(hostProtoViewRef);
|
var hostProtoView = resolveInternalDomProtoView(hostProtoViewRef);
|
||||||
var element = DOM.querySelector(this._document, hostElementSelector);
|
var element = DOM.querySelector(this._document, hostElementSelector);
|
||||||
if (isBlank(element)) {
|
if (isBlank(element)) {
|
||||||
@ -41,21 +43,22 @@ export class DomRenderer extends Renderer {
|
|||||||
return new DomViewRef(this._createView(hostProtoView, element));
|
return new DomViewRef(this._createView(hostProtoView, element));
|
||||||
}
|
}
|
||||||
|
|
||||||
detachFreeHostView(parentHostViewRef:RenderViewRef, hostViewRef:RenderViewRef) {
|
detachFreeHostView(parentHostViewRef: RenderViewRef, hostViewRef: RenderViewRef) {
|
||||||
var hostView = resolveInternalDomView(hostViewRef);
|
var hostView = resolveInternalDomView(hostViewRef);
|
||||||
this._removeViewNodes(hostView);
|
this._removeViewNodes(hostView);
|
||||||
}
|
}
|
||||||
|
|
||||||
createView(protoViewRef:RenderProtoViewRef):RenderViewRef {
|
createView(protoViewRef: RenderProtoViewRef): RenderViewRef {
|
||||||
var protoView = resolveInternalDomProtoView(protoViewRef);
|
var protoView = resolveInternalDomProtoView(protoViewRef);
|
||||||
return new DomViewRef(this._createView(protoView, null));
|
return new DomViewRef(this._createView(protoView, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyView(view:RenderViewRef) {
|
destroyView(view: RenderViewRef) {
|
||||||
// noop for now
|
// noop for now
|
||||||
}
|
}
|
||||||
|
|
||||||
attachComponentView(hostViewRef:RenderViewRef, elementIndex:number, componentViewRef:RenderViewRef) {
|
attachComponentView(hostViewRef: RenderViewRef, elementIndex: number,
|
||||||
|
componentViewRef: RenderViewRef) {
|
||||||
var hostView = resolveInternalDomView(hostViewRef);
|
var hostView = resolveInternalDomView(hostViewRef);
|
||||||
var componentView = resolveInternalDomView(componentViewRef);
|
var componentView = resolveInternalDomView(componentViewRef);
|
||||||
var element = hostView.boundElements[elementIndex];
|
var element = hostView.boundElements[elementIndex];
|
||||||
@ -69,19 +72,20 @@ export class DomRenderer extends Renderer {
|
|||||||
componentView.shadowRoot = shadowRoot;
|
componentView.shadowRoot = shadowRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
setComponentViewRootNodes(componentViewRef:RenderViewRef, rootNodes:List) {
|
setComponentViewRootNodes(componentViewRef: RenderViewRef, rootNodes: List</*node*/ any>) {
|
||||||
var componentView = resolveInternalDomView(componentViewRef);
|
var componentView = resolveInternalDomView(componentViewRef);
|
||||||
this._removeViewNodes(componentView);
|
this._removeViewNodes(componentView);
|
||||||
componentView.rootNodes = rootNodes;
|
componentView.rootNodes = rootNodes;
|
||||||
this._moveViewNodesIntoParent(componentView.shadowRoot, componentView);
|
this._moveViewNodesIntoParent(componentView.shadowRoot, componentView);
|
||||||
}
|
}
|
||||||
|
|
||||||
getHostElement(hostViewRef:RenderViewRef) {
|
getHostElement(hostViewRef: RenderViewRef) {
|
||||||
var hostView = resolveInternalDomView(hostViewRef);
|
var hostView = resolveInternalDomView(hostViewRef);
|
||||||
return hostView.boundElements[0];
|
return hostView.boundElements[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
detachComponentView(hostViewRef:RenderViewRef, boundElementIndex:number, componentViewRef:RenderViewRef) {
|
detachComponentView(hostViewRef: RenderViewRef, boundElementIndex: number,
|
||||||
|
componentViewRef: RenderViewRef) {
|
||||||
var hostView = resolveInternalDomView(hostViewRef);
|
var hostView = resolveInternalDomView(hostViewRef);
|
||||||
var componentView = resolveInternalDomView(componentViewRef);
|
var componentView = resolveInternalDomView(componentViewRef);
|
||||||
this._removeViewNodes(componentView);
|
this._removeViewNodes(componentView);
|
||||||
@ -93,7 +97,8 @@ export class DomRenderer extends Renderer {
|
|||||||
componentView.shadowRoot = null;
|
componentView.shadowRoot = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachViewInContainer(parentViewRef:RenderViewRef, boundElementIndex:number, atIndex:number, viewRef:RenderViewRef) {
|
attachViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
|
||||||
|
viewRef: RenderViewRef) {
|
||||||
var parentView = resolveInternalDomView(parentViewRef);
|
var parentView = resolveInternalDomView(parentViewRef);
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
var viewContainer = this._getOrCreateViewContainer(parentView, boundElementIndex);
|
var viewContainer = this._getOrCreateViewContainer(parentView, boundElementIndex);
|
||||||
@ -118,7 +123,8 @@ export class DomRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
detachViewInContainer(parentViewRef:RenderViewRef, boundElementIndex:number, atIndex:number, viewRef:RenderViewRef) {
|
detachViewInContainer(parentViewRef: RenderViewRef, boundElementIndex: number, atIndex: number,
|
||||||
|
viewRef: RenderViewRef) {
|
||||||
var parentView = resolveInternalDomView(parentViewRef);
|
var parentView = resolveInternalDomView(parentViewRef);
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
var viewContainer = parentView.viewContainers[boundElementIndex];
|
var viewContainer = parentView.viewContainers[boundElementIndex];
|
||||||
@ -137,7 +143,7 @@ export class DomRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hydrateView(viewRef:RenderViewRef) {
|
hydrateView(viewRef: RenderViewRef) {
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
if (view.hydrated) throw new BaseException('The view is already hydrated.');
|
if (view.hydrated) throw new BaseException('The view is already hydrated.');
|
||||||
view.hydrated = true;
|
view.hydrated = true;
|
||||||
@ -149,7 +155,7 @@ export class DomRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//add global events
|
// add global events
|
||||||
view.eventHandlerRemovers = ListWrapper.create();
|
view.eventHandlerRemovers = ListWrapper.create();
|
||||||
var binders = view.proto.elementBinders;
|
var binders = view.proto.elementBinders;
|
||||||
for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) {
|
for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) {
|
||||||
@ -157,7 +163,8 @@ export class DomRenderer extends Renderer {
|
|||||||
if (isPresent(binder.globalEvents)) {
|
if (isPresent(binder.globalEvents)) {
|
||||||
for (var i = 0; i < binder.globalEvents.length; i++) {
|
for (var i = 0; i < binder.globalEvents.length; i++) {
|
||||||
var globalEvent = binder.globalEvents[i];
|
var globalEvent = binder.globalEvents[i];
|
||||||
var remover = this._createGlobalEventListener(view, binderIdx, globalEvent.name, globalEvent.target, globalEvent.fullName);
|
var remover = this._createGlobalEventListener(view, binderIdx, globalEvent.name,
|
||||||
|
globalEvent.target, globalEvent.fullName);
|
||||||
ListWrapper.push(view.eventHandlerRemovers, remover);
|
ListWrapper.push(view.eventHandlerRemovers, remover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,10 +174,10 @@ export class DomRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dehydrateView(viewRef:RenderViewRef) {
|
dehydrateView(viewRef: RenderViewRef) {
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
|
|
||||||
//remove global events
|
// remove global events
|
||||||
for (var i = 0; i < view.eventHandlerRemovers.length; i++) {
|
for (var i = 0; i < view.eventHandlerRemovers.length; i++) {
|
||||||
view.eventHandlerRemovers[i]();
|
view.eventHandlerRemovers[i]();
|
||||||
}
|
}
|
||||||
@ -179,31 +186,35 @@ export class DomRenderer extends Renderer {
|
|||||||
view.hydrated = false;
|
view.hydrated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setElementProperty(viewRef:RenderViewRef, elementIndex:number, propertyName:string, propertyValue:any):void {
|
setElementProperty(viewRef: RenderViewRef, elementIndex: number, propertyName: string,
|
||||||
|
propertyValue: any): void {
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
view.setElementProperty(elementIndex, propertyName, propertyValue);
|
view.setElementProperty(elementIndex, propertyName, propertyValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
callAction(viewRef:RenderViewRef, elementIndex:number, actionExpression:string, actionArgs:any):void {
|
callAction(viewRef: RenderViewRef, elementIndex: number, actionExpression: string,
|
||||||
|
actionArgs: any): void {
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
view.callAction(elementIndex, actionExpression, actionArgs);
|
view.callAction(elementIndex, actionExpression, actionArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
setText(viewRef:RenderViewRef, textNodeIndex:number, text:string):void {
|
setText(viewRef: RenderViewRef, textNodeIndex: number, text: string): void {
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
DOM.setText(view.boundTextNodes[textNodeIndex], text);
|
DOM.setText(view.boundTextNodes[textNodeIndex], text);
|
||||||
}
|
}
|
||||||
|
|
||||||
setEventDispatcher(viewRef:RenderViewRef, dispatcher:any/*api.EventDispatcher*/):void {
|
setEventDispatcher(viewRef: RenderViewRef, dispatcher: any /*api.EventDispatcher*/): void {
|
||||||
var view = resolveInternalDomView(viewRef);
|
var view = resolveInternalDomView(viewRef);
|
||||||
view.eventDispatcher = dispatcher;
|
view.eventDispatcher = dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
_createView(protoView:DomProtoView, inplaceElement): DomView {
|
_createView(protoView: DomProtoView, inplaceElement): DomView {
|
||||||
var rootElementClone = isPresent(inplaceElement) ? inplaceElement : DOM.importIntoDoc(protoView.element);
|
var rootElementClone =
|
||||||
|
isPresent(inplaceElement) ? inplaceElement : DOM.importIntoDoc(protoView.element);
|
||||||
var elementsWithBindingsDynamic;
|
var elementsWithBindingsDynamic;
|
||||||
if (protoView.isTemplateElement) {
|
if (protoView.isTemplateElement) {
|
||||||
elementsWithBindingsDynamic = DOM.querySelectorAll(DOM.content(rootElementClone), NG_BINDING_CLASS_SELECTOR);
|
elementsWithBindingsDynamic =
|
||||||
|
DOM.querySelectorAll(DOM.content(rootElementClone), NG_BINDING_CLASS_SELECTOR);
|
||||||
} else {
|
} else {
|
||||||
elementsWithBindingsDynamic = DOM.getElementsByClassName(rootElementClone, NG_BINDING_CLASS);
|
elementsWithBindingsDynamic = DOM.getElementsByClassName(rootElementClone, NG_BINDING_CLASS);
|
||||||
}
|
}
|
||||||
@ -216,9 +227,10 @@ export class DomRenderer extends Renderer {
|
|||||||
var viewRootNodes;
|
var viewRootNodes;
|
||||||
if (protoView.isTemplateElement) {
|
if (protoView.isTemplateElement) {
|
||||||
var childNode = DOM.firstChild(DOM.content(rootElementClone));
|
var childNode = DOM.firstChild(DOM.content(rootElementClone));
|
||||||
viewRootNodes = []; // TODO(perf): Should be fixed size, since we could pre-compute in in DomProtoView
|
viewRootNodes =
|
||||||
|
[]; // TODO(perf): Should be fixed size, since we could pre-compute in in DomProtoView
|
||||||
// Note: An explicit loop is the fastest way to convert a DOM array into a JS array!
|
// Note: An explicit loop is the fastest way to convert a DOM array into a JS array!
|
||||||
while(childNode != null) {
|
while (childNode != null) {
|
||||||
ListWrapper.push(viewRootNodes, childNode);
|
ListWrapper.push(viewRootNodes, childNode);
|
||||||
childNode = DOM.nextSibling(childNode);
|
childNode = DOM.nextSibling(childNode);
|
||||||
}
|
}
|
||||||
@ -243,7 +255,7 @@ export class DomRenderer extends Renderer {
|
|||||||
// boundTextNodes
|
// boundTextNodes
|
||||||
var childNodes = DOM.childNodes(DOM.templateAwareRoot(element));
|
var childNodes = DOM.childNodes(DOM.templateAwareRoot(element));
|
||||||
var textNodeIndices = binder.textNodeIndices;
|
var textNodeIndices = binder.textNodeIndices;
|
||||||
for (var i = 0; i<textNodeIndices.length; i++) {
|
for (var i = 0; i < textNodeIndices.length; i++) {
|
||||||
ListWrapper.push(boundTextNodes, childNodes[textNodeIndices[i]]);
|
ListWrapper.push(boundTextNodes, childNodes[textNodeIndices[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,10 +267,7 @@ export class DomRenderer extends Renderer {
|
|||||||
contentTags[binderIdx] = contentTag;
|
contentTags[binderIdx] = contentTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
var view = new DomView(
|
var view = new DomView(protoView, viewRootNodes, boundTextNodes, boundElements, contentTags);
|
||||||
protoView, viewRootNodes,
|
|
||||||
boundTextNodes, boundElements, contentTags
|
|
||||||
);
|
|
||||||
|
|
||||||
for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) {
|
for (var binderIdx = 0; binderIdx < binders.length; binderIdx++) {
|
||||||
var binder = binders[binderIdx];
|
var binder = binders[binderIdx];
|
||||||
@ -281,7 +290,8 @@ export class DomRenderer extends Renderer {
|
|||||||
// events
|
// events
|
||||||
if (isPresent(binder.eventLocals) && isPresent(binder.localEvents)) {
|
if (isPresent(binder.eventLocals) && isPresent(binder.localEvents)) {
|
||||||
for (var i = 0; i < binder.localEvents.length; i++) {
|
for (var i = 0; i < binder.localEvents.length; i++) {
|
||||||
this._createEventListener(view, element, binderIdx, binder.localEvents[i].name, binder.eventLocals);
|
this._createEventListener(view, element, binderIdx, binder.localEvents[i].name,
|
||||||
|
binder.eventLocals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,9 +300,8 @@ export class DomRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createEventListener(view, element, elementIndex, eventName, eventLocals) {
|
_createEventListener(view, element, elementIndex, eventName, eventLocals) {
|
||||||
this._eventManager.addEventListener(element, eventName, (event) => {
|
this._eventManager.addEventListener(
|
||||||
view.dispatchEvent(elementIndex, eventName, event);
|
element, eventName, (event) => { view.dispatchEvent(elementIndex, eventName, event); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -317,7 +326,7 @@ export class DomRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_getOrCreateViewContainer(parentView:DomView, boundElementIndex) {
|
_getOrCreateViewContainer(parentView: DomView, boundElementIndex) {
|
||||||
var vc = parentView.viewContainers[boundElementIndex];
|
var vc = parentView.viewContainers[boundElementIndex];
|
||||||
if (isBlank(vc)) {
|
if (isBlank(vc)) {
|
||||||
vc = new DomViewContainer();
|
vc = new DomViewContainer();
|
||||||
@ -327,9 +336,7 @@ export class DomRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createGlobalEventListener(view, elementIndex, eventName, eventTarget, fullName): Function {
|
_createGlobalEventListener(view, elementIndex, eventName, eventTarget, fullName): Function {
|
||||||
return this._eventManager.addGlobalEventListener(eventTarget, eventName, (event) => {
|
return this._eventManager.addGlobalEventListener(
|
||||||
view.dispatchEvent(elementIndex, fullName, event);
|
eventTarget, eventName, (event) => { view.dispatchEvent(elementIndex, fullName, event); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -20,18 +20,18 @@ export class EventManager {
|
|||||||
addEventListener(element, eventName: string, handler: Function) {
|
addEventListener(element, eventName: string, handler: Function) {
|
||||||
var withoutBubbleSymbol = this._removeBubbleSymbol(eventName);
|
var withoutBubbleSymbol = this._removeBubbleSymbol(eventName);
|
||||||
var plugin = this._findPluginFor(withoutBubbleSymbol);
|
var plugin = this._findPluginFor(withoutBubbleSymbol);
|
||||||
plugin.addEventListener(element, withoutBubbleSymbol, handler, withoutBubbleSymbol != eventName);
|
plugin.addEventListener(element, withoutBubbleSymbol, handler,
|
||||||
|
withoutBubbleSymbol != eventName);
|
||||||
}
|
}
|
||||||
|
|
||||||
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
|
addGlobalEventListener(target: string, eventName: string, handler: Function): Function {
|
||||||
var withoutBubbleSymbol = this._removeBubbleSymbol(eventName);
|
var withoutBubbleSymbol = this._removeBubbleSymbol(eventName);
|
||||||
var plugin = this._findPluginFor(withoutBubbleSymbol);
|
var plugin = this._findPluginFor(withoutBubbleSymbol);
|
||||||
return plugin.addGlobalEventListener(target, withoutBubbleSymbol, handler, withoutBubbleSymbol != eventName);
|
return plugin.addGlobalEventListener(target, withoutBubbleSymbol, handler,
|
||||||
|
withoutBubbleSymbol != eventName);
|
||||||
}
|
}
|
||||||
|
|
||||||
getZone(): NgZone {
|
getZone(): NgZone { return this._zone; }
|
||||||
return this._zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
_findPluginFor(eventName: string): EventManagerPlugin {
|
_findPluginFor(eventName: string): EventManagerPlugin {
|
||||||
var plugins = this._plugins;
|
var plugins = this._plugins;
|
||||||
@ -56,15 +56,14 @@ export class EventManagerPlugin {
|
|||||||
// That is equivalent to having supporting $event.target
|
// That is equivalent to having supporting $event.target
|
||||||
// The bubbling flag (currently ^) is stripped before calling the supports and
|
// The bubbling flag (currently ^) is stripped before calling the supports and
|
||||||
// addEventListener methods.
|
// addEventListener methods.
|
||||||
supports(eventName: string): boolean {
|
supports(eventName: string): boolean { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
||||||
throw "not implemented";
|
throw "not implemented";
|
||||||
}
|
}
|
||||||
|
|
||||||
addGlobalEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean): Function {
|
addGlobalEventListener(element, eventName: string, handler: Function,
|
||||||
|
shouldSupportBubble: boolean): Function {
|
||||||
throw "not implemented";
|
throw "not implemented";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,37 +73,30 @@ export class DomEventsPlugin extends EventManagerPlugin {
|
|||||||
|
|
||||||
// This plugin should come last in the list of plugins, because it accepts all
|
// This plugin should come last in the list of plugins, because it accepts all
|
||||||
// events.
|
// events.
|
||||||
supports(eventName: string): boolean {
|
supports(eventName: string): boolean { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
||||||
var outsideHandler = this._getOutsideHandler(shouldSupportBubble, element, handler, this.manager._zone);
|
var outsideHandler =
|
||||||
this.manager._zone.runOutsideAngular(() => {
|
this._getOutsideHandler(shouldSupportBubble, element, handler, this.manager._zone);
|
||||||
DOM.on(element, eventName, outsideHandler);
|
this.manager._zone.runOutsideAngular(() => { DOM.on(element, eventName, outsideHandler); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addGlobalEventListener(target:string, eventName: string, handler: Function, shouldSupportBubble: boolean): Function {
|
addGlobalEventListener(target: string, eventName: string, handler: Function,
|
||||||
|
shouldSupportBubble: boolean): Function {
|
||||||
var element = DOM.getGlobalEventTarget(target);
|
var element = DOM.getGlobalEventTarget(target);
|
||||||
var outsideHandler = this._getOutsideHandler(shouldSupportBubble, element, handler, this.manager._zone);
|
var outsideHandler =
|
||||||
return this.manager._zone.runOutsideAngular(() => {
|
this._getOutsideHandler(shouldSupportBubble, element, handler, this.manager._zone);
|
||||||
return DOM.onAndCancel(element, eventName, outsideHandler);
|
return this.manager._zone.runOutsideAngular(
|
||||||
});
|
() => { return DOM.onAndCancel(element, eventName, outsideHandler); });
|
||||||
}
|
}
|
||||||
|
|
||||||
_getOutsideHandler(shouldSupportBubble: boolean, element, handler: Function, zone: NgZone) {
|
_getOutsideHandler(shouldSupportBubble: boolean, element, handler: Function, zone: NgZone) {
|
||||||
return shouldSupportBubble ?
|
return shouldSupportBubble ? DomEventsPlugin.bubbleCallback(element, handler, zone) :
|
||||||
DomEventsPlugin.bubbleCallback(element, handler, zone) :
|
DomEventsPlugin.sameElementCallback(element, handler, zone);
|
||||||
DomEventsPlugin.sameElementCallback(element, handler, zone);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static sameElementCallback(element, handler, zone) {
|
static sameElementCallback(element, handler, zone) {
|
||||||
return (event) => {
|
return (event) => { if (event.target === element) { zone.run(() => handler(event)); } };
|
||||||
if (event.target === element) {
|
|
||||||
zone.run(() => handler(event));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bubbleCallback(element, handler, zone) {
|
static bubbleCallback(element, handler, zone) {
|
@ -41,9 +41,7 @@ var _eventNames = {
|
|||||||
|
|
||||||
|
|
||||||
export class HammerGesturesPluginCommon extends EventManagerPlugin {
|
export class HammerGesturesPluginCommon extends EventManagerPlugin {
|
||||||
constructor() {
|
constructor() { super(); }
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
supports(eventName: string): boolean {
|
supports(eventName: string): boolean {
|
||||||
eventName = eventName.toLowerCase();
|
eventName = eventName.toLowerCase();
|
@ -2,11 +2,9 @@ import {HammerGesturesPluginCommon} from './hammer_common';
|
|||||||
import {isPresent, BaseException} from 'angular2/src/facade/lang';
|
import {isPresent, BaseException} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
|
export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
|
||||||
constructor() {
|
constructor() { super(); }
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
supports(eventName:string):boolean {
|
supports(eventName: string): boolean {
|
||||||
if (!super.supports(eventName)) return false;
|
if (!super.supports(eventName)) return false;
|
||||||
|
|
||||||
if (!isPresent(window.Hammer)) {
|
if (!isPresent(window.Hammer)) {
|
||||||
@ -16,22 +14,19 @@ export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListener(element, eventName:string, handler:Function, shouldSupportBubble: boolean) {
|
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
||||||
if (shouldSupportBubble) throw new BaseException('Hammer.js plugin does not support bubbling gestures.');
|
if (shouldSupportBubble)
|
||||||
|
throw new BaseException('Hammer.js plugin does not support bubbling gestures.');
|
||||||
var zone = this.manager.getZone();
|
var zone = this.manager.getZone();
|
||||||
eventName = eventName.toLowerCase();
|
eventName = eventName.toLowerCase();
|
||||||
|
|
||||||
zone.runOutsideAngular(function () {
|
zone.runOutsideAngular(function() {
|
||||||
// Creating the manager bind events, must be done outside of angular
|
// Creating the manager bind events, must be done outside of angular
|
||||||
var mc = new Hammer(element);
|
var mc = new Hammer(element);
|
||||||
mc.get('pinch').set({enable: true});
|
mc.get('pinch').set({enable: true});
|
||||||
mc.get('rotate').set({enable: true});
|
mc.get('rotate').set({enable: true});
|
||||||
|
|
||||||
mc.on(eventName, function (eventObj) {
|
mc.on(eventName, function(eventObj) { zone.run(function() { handler(eventObj); }); });
|
||||||
zone.run(function () {
|
|
||||||
handler(eventObj);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,31 +1,37 @@
|
|||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {isPresent, isBlank, StringWrapper, RegExpWrapper, BaseException, NumberWrapper} from 'angular2/src/facade/lang';
|
import {
|
||||||
|
isPresent,
|
||||||
|
isBlank,
|
||||||
|
StringWrapper,
|
||||||
|
RegExpWrapper,
|
||||||
|
BaseException,
|
||||||
|
NumberWrapper
|
||||||
|
} from 'angular2/src/facade/lang';
|
||||||
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {EventManagerPlugin} from './event_manager';
|
import {EventManagerPlugin} from './event_manager';
|
||||||
|
|
||||||
var modifierKeys = ['alt', 'control', 'meta', 'shift'];
|
var modifierKeys = ['alt', 'control', 'meta', 'shift'];
|
||||||
var modifierKeyGetters = {
|
var modifierKeyGetters =
|
||||||
'alt': (event) => event.altKey,
|
{
|
||||||
'control': (event) => event.ctrlKey,
|
'alt': (event) => event.altKey,
|
||||||
'meta': (event) => event.metaKey,
|
'control': (event) => event.ctrlKey,
|
||||||
'shift': (event) => event.shiftKey
|
'meta': (event) => event.metaKey,
|
||||||
}
|
'shift': (event) => event.shiftKey
|
||||||
|
}
|
||||||
|
|
||||||
export class KeyEventsPlugin extends EventManagerPlugin {
|
export class KeyEventsPlugin extends EventManagerPlugin {
|
||||||
constructor() {
|
constructor() { super(); }
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
supports(eventName: string): boolean {
|
supports(eventName: string): boolean {
|
||||||
return isPresent(KeyEventsPlugin.parseEventName(eventName));
|
return isPresent(KeyEventsPlugin.parseEventName(eventName));
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListener(element, eventName: string, handler: Function,
|
addEventListener(element, eventName: string, handler: Function, shouldSupportBubble: boolean) {
|
||||||
shouldSupportBubble: boolean) {
|
|
||||||
var parsedEvent = KeyEventsPlugin.parseEventName(eventName);
|
var parsedEvent = KeyEventsPlugin.parseEventName(eventName);
|
||||||
|
|
||||||
var outsideHandler = KeyEventsPlugin.eventCallback(element, shouldSupportBubble,
|
var outsideHandler = KeyEventsPlugin.eventCallback(element, shouldSupportBubble,
|
||||||
StringMapWrapper.get(parsedEvent, 'fullKey'), handler, this.manager.getZone());
|
StringMapWrapper.get(parsedEvent, 'fullKey'),
|
||||||
|
handler, this.manager.getZone());
|
||||||
|
|
||||||
this.manager.getZone().runOutsideAngular(() => {
|
this.manager.getZone().runOutsideAngular(() => {
|
||||||
DOM.on(element, StringMapWrapper.get(parsedEvent, 'domEventName'), outsideHandler);
|
DOM.on(element, StringMapWrapper.get(parsedEvent, 'domEventName'), outsideHandler);
|
||||||
@ -36,7 +42,9 @@ export class KeyEventsPlugin extends EventManagerPlugin {
|
|||||||
eventName = eventName.toLowerCase();
|
eventName = eventName.toLowerCase();
|
||||||
var parts = eventName.split('.');
|
var parts = eventName.split('.');
|
||||||
var domEventName = ListWrapper.removeAt(parts, 0);
|
var domEventName = ListWrapper.removeAt(parts, 0);
|
||||||
if ((parts.length === 0) || !(StringWrapper.equals(domEventName, 'keydown') || StringWrapper.equals(domEventName, 'keyup'))) {
|
if ((parts.length === 0) ||
|
||||||
|
!(StringWrapper.equals(domEventName, 'keydown') ||
|
||||||
|
StringWrapper.equals(domEventName, 'keyup'))) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var key = ListWrapper.removeLast(parts);
|
var key = ListWrapper.removeLast(parts);
|
||||||
@ -55,10 +63,7 @@ export class KeyEventsPlugin extends EventManagerPlugin {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {'domEventName': domEventName, 'fullKey': fullKey};
|
||||||
'domEventName': domEventName,
|
|
||||||
'fullKey': fullKey
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static getEventFullKey(event): string {
|
static getEventFullKey(event): string {
|
||||||
@ -66,9 +71,9 @@ export class KeyEventsPlugin extends EventManagerPlugin {
|
|||||||
var key = DOM.getEventKey(event);
|
var key = DOM.getEventKey(event);
|
||||||
key = key.toLowerCase();
|
key = key.toLowerCase();
|
||||||
if (StringWrapper.equals(key, ' ')) {
|
if (StringWrapper.equals(key, ' ')) {
|
||||||
key = 'space'; // for readability
|
key = 'space'; // for readability
|
||||||
} else if (StringWrapper.equals(key, '.')) {
|
} else if (StringWrapper.equals(key, '.')) {
|
||||||
key = 'dot'; // because '.' is used as a separator in event names
|
key = 'dot'; // because '.' is used as a separator in event names
|
||||||
}
|
}
|
||||||
ListWrapper.forEach(modifierKeys, (modifierName) => {
|
ListWrapper.forEach(modifierKeys, (modifierName) => {
|
||||||
if (modifierName != key) {
|
if (modifierName != key) {
|
||||||
@ -83,11 +88,10 @@ export class KeyEventsPlugin extends EventManagerPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static eventCallback(element, shouldSupportBubble, fullKey, handler, zone) {
|
static eventCallback(element, shouldSupportBubble, fullKey, handler, zone) {
|
||||||
return (event) => {
|
return (event) => { var correctElement = shouldSupportBubble || event.target === element;
|
||||||
var correctElement = shouldSupportBubble || event.target === element;
|
if (correctElement && KeyEventsPlugin.getEventFullKey(event) === fullKey) {
|
||||||
if (correctElement && KeyEventsPlugin.getEventFullKey(event) === fullKey) {
|
zone.run(() => handler(event));
|
||||||
zone.run(() => handler(event));
|
}
|
||||||
}
|
};
|
||||||
};
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@ -4,8 +4,8 @@ import {isPresent} from 'angular2/src/facade/lang';
|
|||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
class ContentStrategy {
|
class ContentStrategy {
|
||||||
nodes:List;
|
nodes: List</*node*/ any>;
|
||||||
insert(nodes:List){}
|
insert(nodes: List</*node*/ any>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,7 +26,7 @@ class RenderedContent extends ContentStrategy {
|
|||||||
|
|
||||||
// Inserts the nodes in between the start and end scripts.
|
// Inserts the nodes in between the start and end scripts.
|
||||||
// Previous content is removed.
|
// Previous content is removed.
|
||||||
insert(nodes:List) {
|
insert(nodes: List</*node*/ any>) {
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
DOM.insertAllBefore(this.endScript, nodes);
|
DOM.insertAllBefore(this.endScript, nodes);
|
||||||
this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]);
|
this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]);
|
||||||
@ -34,8 +34,7 @@ class RenderedContent extends ContentStrategy {
|
|||||||
|
|
||||||
_removeNodesUntil(node) {
|
_removeNodesUntil(node) {
|
||||||
var p = DOM.parentElement(this.beginScript);
|
var p = DOM.parentElement(this.beginScript);
|
||||||
for (var next = DOM.nextSibling(this.beginScript);
|
for (var next = DOM.nextSibling(this.beginScript); next !== node;
|
||||||
next !== node;
|
|
||||||
next = DOM.nextSibling(this.beginScript)) {
|
next = DOM.nextSibling(this.beginScript)) {
|
||||||
DOM.removeChild(p, next);
|
DOM.removeChild(p, next);
|
||||||
}
|
}
|
||||||
@ -48,15 +47,15 @@ class RenderedContent extends ContentStrategy {
|
|||||||
* and thus does not get rendered but only affect the distribution of its parent component.
|
* and thus does not get rendered but only affect the distribution of its parent component.
|
||||||
*/
|
*/
|
||||||
class IntermediateContent extends ContentStrategy {
|
class IntermediateContent extends ContentStrategy {
|
||||||
destinationLightDom:ldModule.LightDom;
|
destinationLightDom: ldModule.LightDom;
|
||||||
|
|
||||||
constructor(destinationLightDom:ldModule.LightDom) {
|
constructor(destinationLightDom: ldModule.LightDom) {
|
||||||
super();
|
super();
|
||||||
this.nodes = [];
|
this.nodes = [];
|
||||||
this.destinationLightDom = destinationLightDom;
|
this.destinationLightDom = destinationLightDom;
|
||||||
}
|
}
|
||||||
|
|
||||||
insert(nodes:List) {
|
insert(nodes: List</*node*/ any>) {
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
this.destinationLightDom.redistribute();
|
this.destinationLightDom.redistribute();
|
||||||
}
|
}
|
||||||
@ -64,27 +63,22 @@ class IntermediateContent extends ContentStrategy {
|
|||||||
|
|
||||||
|
|
||||||
export class Content {
|
export class Content {
|
||||||
select:string;
|
select: string;
|
||||||
_strategy:ContentStrategy;
|
private _strategy: ContentStrategy;
|
||||||
contentStartElement;
|
contentStartElement;
|
||||||
|
|
||||||
constructor(contentStartEl, selector:string) {
|
constructor(contentStartEl, selector: string) {
|
||||||
this.select = selector;
|
this.select = selector;
|
||||||
this.contentStartElement = contentStartEl;
|
this.contentStartElement = contentStartEl;
|
||||||
this._strategy = null;
|
this._strategy = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
init(destinationLightDom:ldModule.LightDom) {
|
init(destinationLightDom: ldModule.LightDom) {
|
||||||
this._strategy = isPresent(destinationLightDom) ?
|
this._strategy = isPresent(destinationLightDom) ? new IntermediateContent(destinationLightDom) :
|
||||||
new IntermediateContent(destinationLightDom) :
|
new RenderedContent(this.contentStartElement);
|
||||||
new RenderedContent(this.contentStartElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes():List {
|
nodes(): List</*node*/ any> { return this._strategy.nodes; }
|
||||||
return this._strategy.nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
insert(nodes:List) {
|
insert(nodes: List</*node*/ any>) { this._strategy.insert(nodes); }
|
||||||
this._strategy.insert(nodes);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,7 +7,11 @@ import {StyleInliner} from 'angular2/src/render/dom/shadow_dom/style_inliner';
|
|||||||
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
import {StyleUrlResolver} from 'angular2/src/render/dom/shadow_dom/style_url_resolver';
|
||||||
import {EmulatedUnscopedShadowDomStrategy} from './emulated_unscoped_shadow_dom_strategy';
|
import {EmulatedUnscopedShadowDomStrategy} from './emulated_unscoped_shadow_dom_strategy';
|
||||||
import {
|
import {
|
||||||
getContentAttribute, getHostAttribute, getComponentId, shimCssForComponent, insertStyleElement
|
getContentAttribute,
|
||||||
|
getHostAttribute,
|
||||||
|
getComponentId,
|
||||||
|
shimCssForComponent,
|
||||||
|
insertStyleElement
|
||||||
} from './util';
|
} from './util';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,29 +34,28 @@ export class EmulatedScopedShadowDomStrategy extends EmulatedUnscopedShadowDomSt
|
|||||||
this.styleInliner = styleInliner;
|
this.styleInliner = styleInliner;
|
||||||
}
|
}
|
||||||
|
|
||||||
processStyleElement(hostComponentId:string, templateUrl:string, styleEl):Promise {
|
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
|
||||||
var cssText = DOM.getText(styleEl);
|
var cssText = DOM.getText(styleEl);
|
||||||
|
|
||||||
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
|
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
|
||||||
var css = this.styleInliner.inlineImports(cssText, templateUrl);
|
var inlinedCss = this.styleInliner.inlineImports(cssText, templateUrl);
|
||||||
|
|
||||||
if (PromiseWrapper.isPromise(css)) {
|
if (isPresent(inlinedCss.asyncResult)) {
|
||||||
DOM.setText(styleEl, '');
|
DOM.setText(styleEl, '');
|
||||||
return css.then((css) => {
|
return inlinedCss.asyncResult.then((css) => {
|
||||||
css = shimCssForComponent(css, hostComponentId);
|
css = shimCssForComponent(css, hostComponentId);
|
||||||
DOM.setText(styleEl, css);
|
DOM.setText(styleEl, css);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
css = shimCssForComponent(css, hostComponentId);
|
var css = shimCssForComponent(inlinedCss.syncResult, hostComponentId);
|
||||||
DOM.setText(styleEl, css);
|
DOM.setText(styleEl, css);
|
||||||
|
DOM.remove(styleEl);
|
||||||
|
insertStyleElement(this.styleHost, styleEl);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOM.remove(styleEl);
|
|
||||||
insertStyleElement(this.styleHost, styleEl);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
processElement(hostComponentId:string, elementComponentId:string, element) {
|
processElement(hostComponentId: string, elementComponentId: string, element) {
|
||||||
// Shim the element as a child of the compiled component
|
// Shim the element as a child of the compiled component
|
||||||
if (isPresent(hostComponentId)) {
|
if (isPresent(hostComponentId)) {
|
||||||
var contentAttribute = getContentAttribute(getComponentId(hostComponentId));
|
var contentAttribute = getContentAttribute(getComponentId(hostComponentId));
|
@ -28,19 +28,15 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
|
|||||||
this.styleHost = styleHost;
|
this.styleHost = styleHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasNativeContentElement():boolean {
|
hasNativeContentElement(): boolean { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareShadowRoot(el) {
|
prepareShadowRoot(el) { return el; }
|
||||||
return el;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructLightDom(lightDomView:viewModule.DomView, el): LightDom {
|
constructLightDom(lightDomView: viewModule.DomView, el): LightDom {
|
||||||
return new LightDom(lightDomView, el);
|
return new LightDom(lightDomView, el);
|
||||||
}
|
}
|
||||||
|
|
||||||
processStyleElement(hostComponentId:string, templateUrl:string, styleEl):Promise {
|
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
|
||||||
var cssText = DOM.getText(styleEl);
|
var cssText = DOM.getText(styleEl);
|
||||||
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
|
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
|
||||||
DOM.setText(styleEl, cssText);
|
DOM.setText(styleEl, cssText);
|
@ -9,7 +9,7 @@ export class DestinationLightDom {}
|
|||||||
|
|
||||||
class _Root {
|
class _Root {
|
||||||
node;
|
node;
|
||||||
boundElementIndex:number;
|
boundElementIndex: number;
|
||||||
|
|
||||||
constructor(node, boundElementIndex) {
|
constructor(node, boundElementIndex) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
@ -21,32 +21,26 @@ class _Root {
|
|||||||
// once interfaces are supported
|
// once interfaces are supported
|
||||||
export class LightDom {
|
export class LightDom {
|
||||||
// The light DOM of the element is enclosed inside the lightDomView
|
// The light DOM of the element is enclosed inside the lightDomView
|
||||||
lightDomView:viewModule.DomView;
|
lightDomView: viewModule.DomView;
|
||||||
// The shadow DOM
|
// The shadow DOM
|
||||||
shadowDomView:viewModule.DomView;
|
shadowDomView: viewModule.DomView;
|
||||||
// The nodes of the light DOM
|
// The nodes of the light DOM
|
||||||
nodes:List;
|
nodes: List</*node*/ any>;
|
||||||
roots:List<_Root>;
|
private _roots: List<_Root>;
|
||||||
|
|
||||||
constructor(lightDomView:viewModule.DomView, element) {
|
constructor(lightDomView: viewModule.DomView, element) {
|
||||||
this.lightDomView = lightDomView;
|
this.lightDomView = lightDomView;
|
||||||
this.nodes = DOM.childNodesAsList(element);
|
this.nodes = DOM.childNodesAsList(element);
|
||||||
|
|
||||||
this.roots = null;
|
this._roots = null;
|
||||||
this.shadowDomView = null;
|
this.shadowDomView = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachShadowDomView(shadowDomView:viewModule.DomView) {
|
attachShadowDomView(shadowDomView: viewModule.DomView) { this.shadowDomView = shadowDomView; }
|
||||||
this.shadowDomView = shadowDomView;
|
|
||||||
}
|
|
||||||
|
|
||||||
detachShadowDomView() {
|
detachShadowDomView() { this.shadowDomView = null; }
|
||||||
this.shadowDomView = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
redistribute() {
|
redistribute() { redistributeNodes(this.contentTags(), this.expandedDomNodes()); }
|
||||||
redistributeNodes(this.contentTags(), this.expandedDomNodes());
|
|
||||||
}
|
|
||||||
|
|
||||||
contentTags(): List<Content> {
|
contentTags(): List<Content> {
|
||||||
if (isPresent(this.shadowDomView)) {
|
if (isPresent(this.shadowDomView)) {
|
||||||
@ -57,19 +51,18 @@ export class LightDom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Collects the Content directives from the view and all its child views
|
// Collects the Content directives from the view and all its child views
|
||||||
_collectAllContentTags(view: viewModule.DomView, acc:List<Content>):List<Content> {
|
private _collectAllContentTags(view: viewModule.DomView, acc: List<Content>): List<Content> {
|
||||||
var contentTags = view.contentTags;
|
var contentTags = view.contentTags;
|
||||||
var vcs = view.viewContainers;
|
var vcs = view.viewContainers;
|
||||||
for (var i=0; i<vcs.length; i++) {
|
for (var i = 0; i < vcs.length; i++) {
|
||||||
var vc = vcs[i];
|
var vc = vcs[i];
|
||||||
var contentTag = contentTags[i];
|
var contentTag = contentTags[i];
|
||||||
if (isPresent(contentTag)) {
|
if (isPresent(contentTag)) {
|
||||||
ListWrapper.push(acc, contentTag);
|
ListWrapper.push(acc, contentTag);
|
||||||
}
|
}
|
||||||
if (isPresent(vc)) {
|
if (isPresent(vc)) {
|
||||||
ListWrapper.forEach(vc.contentTagContainers(), (view) => {
|
ListWrapper.forEach(vc.contentTagContainers(),
|
||||||
this._collectAllContentTags(view, acc);
|
(view) => { this._collectAllContentTags(view, acc); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
@ -79,12 +72,11 @@ export class LightDom {
|
|||||||
// - nodes from enclosed ViewContainers,
|
// - nodes from enclosed ViewContainers,
|
||||||
// - nodes from enclosed content tags,
|
// - nodes from enclosed content tags,
|
||||||
// - plain DOM nodes
|
// - plain DOM nodes
|
||||||
expandedDomNodes():List {
|
expandedDomNodes(): List</*node*/ any> {
|
||||||
var res = [];
|
var res = [];
|
||||||
|
|
||||||
var roots = this._roots();
|
var roots = this._findRoots();
|
||||||
for (var i = 0; i < roots.length; ++i) {
|
for (var i = 0; i < roots.length; ++i) {
|
||||||
|
|
||||||
var root = roots[i];
|
var root = roots[i];
|
||||||
if (isPresent(root.boundElementIndex)) {
|
if (isPresent(root.boundElementIndex)) {
|
||||||
var vc = this.lightDomView.viewContainers[root.boundElementIndex];
|
var vc = this.lightDomView.viewContainers[root.boundElementIndex];
|
||||||
@ -105,14 +97,14 @@ export class LightDom {
|
|||||||
|
|
||||||
// Returns a list of Roots for all the nodes of the light DOM.
|
// Returns a list of Roots for all the nodes of the light DOM.
|
||||||
// The Root object contains the DOM node and its corresponding boundElementIndex
|
// The Root object contains the DOM node and its corresponding boundElementIndex
|
||||||
_roots() {
|
private _findRoots() {
|
||||||
if (isPresent(this.roots)) return this.roots;
|
if (isPresent(this._roots)) return this._roots;
|
||||||
|
|
||||||
var boundElements = this.lightDomView.boundElements;
|
var boundElements = this.lightDomView.boundElements;
|
||||||
|
|
||||||
this.roots = ListWrapper.map(this.nodes, (n) => {
|
this._roots = ListWrapper.map(this.nodes, (n) => {
|
||||||
var boundElementIndex = null;
|
var boundElementIndex = null;
|
||||||
for (var i=0; i<boundElements.length; i++) {
|
for (var i = 0; i < boundElements.length; i++) {
|
||||||
var boundEl = boundElements[i];
|
var boundEl = boundElements[i];
|
||||||
if (isPresent(boundEl) && boundEl === n) {
|
if (isPresent(boundEl) && boundEl === n) {
|
||||||
boundElementIndex = i;
|
boundElementIndex = i;
|
||||||
@ -122,12 +114,12 @@ export class LightDom {
|
|||||||
return new _Root(n, boundElementIndex);
|
return new _Root(n, boundElementIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.roots;
|
return this._roots;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Projects the light DOM into the shadow DOM
|
// Projects the light DOM into the shadow DOM
|
||||||
function redistributeNodes(contents:List<Content>, nodes:List) {
|
function redistributeNodes(contents: List<Content>, nodes: List</*node*/ any>) {
|
||||||
for (var i = 0; i < contents.length; ++i) {
|
for (var i = 0; i < contents.length; ++i) {
|
||||||
var content = contents[i];
|
var content = contents[i];
|
||||||
var select = content.select;
|
var select = content.select;
|
@ -19,11 +19,9 @@ export class NativeShadowDomStrategy extends ShadowDomStrategy {
|
|||||||
this.styleUrlResolver = styleUrlResolver;
|
this.styleUrlResolver = styleUrlResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareShadowRoot(el) {
|
prepareShadowRoot(el) { return DOM.createShadowRoot(el); }
|
||||||
return DOM.createShadowRoot(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
processStyleElement(hostComponentId:string, templateUrl:string, styleEl):Promise {
|
processStyleElement(hostComponentId: string, templateUrl: string, styleEl): Promise<any> {
|
||||||
var cssText = DOM.getText(styleEl);
|
var cssText = DOM.getText(styleEl);
|
||||||
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
|
cssText = this.styleUrlResolver.resolveUrls(cssText, templateUrl);
|
||||||
DOM.setText(styleEl, cssText);
|
DOM.setText(styleEl, cssText);
|
@ -16,7 +16,8 @@ import {
|
|||||||
*
|
*
|
||||||
* Please make sure to keep to edits in sync with the source file.
|
* Please make sure to keep to edits in sync with the source file.
|
||||||
*
|
*
|
||||||
* Source: https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js
|
* Source:
|
||||||
|
* https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js
|
||||||
*
|
*
|
||||||
* The original file level comment is reproduced below
|
* The original file level comment is reproduced below
|
||||||
*/
|
*/
|
||||||
@ -139,9 +140,7 @@ import {
|
|||||||
export class ShadowCss {
|
export class ShadowCss {
|
||||||
strictStyling: boolean;
|
strictStyling: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() { this.strictStyling = true; }
|
||||||
this.strictStyling = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shim a style element with the given selector. Returns cssText that can
|
* Shim a style element with the given selector. Returns cssText that can
|
||||||
@ -186,9 +185,8 @@ export class ShadowCss {
|
|||||||
**/
|
**/
|
||||||
_insertPolyfillDirectivesInCssText(cssText: string): string {
|
_insertPolyfillDirectivesInCssText(cssText: string): string {
|
||||||
// Difference with webcomponents.js: does not handle comments
|
// Difference with webcomponents.js: does not handle comments
|
||||||
return StringWrapper.replaceAllMapped(cssText, _cssContentNextSelectorRe, function(m) {
|
return StringWrapper.replaceAllMapped(cssText, _cssContentNextSelectorRe,
|
||||||
return m[1] + '{';
|
function(m) { return m[1] + '{'; });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -225,16 +223,14 @@ export class ShadowCss {
|
|||||||
* scopeName .foo { ... }
|
* scopeName .foo { ... }
|
||||||
*/
|
*/
|
||||||
_scopeCssText(cssText: string, scopeSelector: string, hostSelector: string): string {
|
_scopeCssText(cssText: string, scopeSelector: string, hostSelector: string): string {
|
||||||
|
|
||||||
var unscoped = this._extractUnscopedRulesFromCssText(cssText);
|
var unscoped = this._extractUnscopedRulesFromCssText(cssText);
|
||||||
cssText = this._insertPolyfillHostInCssText(cssText);
|
cssText = this._insertPolyfillHostInCssText(cssText);
|
||||||
cssText = this._convertColonHost(cssText);
|
cssText = this._convertColonHost(cssText);
|
||||||
cssText = this._convertColonHostContext(cssText);
|
cssText = this._convertColonHostContext(cssText);
|
||||||
cssText = this._convertShadowDOMSelectors(cssText);
|
cssText = this._convertShadowDOMSelectors(cssText);
|
||||||
if (isPresent(scopeSelector)) {
|
if (isPresent(scopeSelector)) {
|
||||||
_withCssRules(cssText, (rules) => {
|
_withCssRules(cssText,
|
||||||
cssText = this._scopeRules(rules, scopeSelector, hostSelector);
|
(rules) => { cssText = this._scopeRules(rules, scopeSelector, hostSelector); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
cssText = cssText + '\n' + unscoped;
|
cssText = cssText + '\n' + unscoped;
|
||||||
return cssText.trim();
|
return cssText.trim();
|
||||||
@ -276,8 +272,7 @@ export class ShadowCss {
|
|||||||
* scopeName.foo > .bar
|
* scopeName.foo > .bar
|
||||||
*/
|
*/
|
||||||
_convertColonHost(cssText: string): string {
|
_convertColonHost(cssText: string): string {
|
||||||
return this._convertColonRule(cssText, _cssColonHostRe,
|
return this._convertColonRule(cssText, _cssColonHostRe, this._colonHostPartReplacer);
|
||||||
this._colonHostPartReplacer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -297,7 +292,7 @@ export class ShadowCss {
|
|||||||
*/
|
*/
|
||||||
_convertColonHostContext(cssText: string): string {
|
_convertColonHostContext(cssText: string): string {
|
||||||
return this._convertColonRule(cssText, _cssColonHostContextRe,
|
return this._convertColonRule(cssText, _cssColonHostContextRe,
|
||||||
this._colonHostContextPartReplacer);
|
this._colonHostContextPartReplacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
_convertColonRule(cssText: string, regExp: RegExp, partReplacer: Function): string {
|
_convertColonRule(cssText: string, regExp: RegExp, partReplacer: Function): string {
|
||||||
@ -349,7 +344,8 @@ export class ShadowCss {
|
|||||||
var rule = cssRules[i];
|
var rule = cssRules[i];
|
||||||
if (DOM.isStyleRule(rule) || DOM.isPageRule(rule)) {
|
if (DOM.isStyleRule(rule) || DOM.isPageRule(rule)) {
|
||||||
cssText += this._scopeSelector(rule.selectorText, scopeSelector, hostSelector,
|
cssText += this._scopeSelector(rule.selectorText, scopeSelector, hostSelector,
|
||||||
this.strictStyling) + ' {\n';
|
this.strictStyling) +
|
||||||
|
' {\n';
|
||||||
cssText += this._propertiesFromRule(rule) + '\n}\n\n';
|
cssText += this._propertiesFromRule(rule) + '\n}\n\n';
|
||||||
} else if (DOM.isMediaRule(rule)) {
|
} else if (DOM.isMediaRule(rule)) {
|
||||||
cssText += '@media ' + rule.media.mediaText + ' {\n';
|
cssText += '@media ' + rule.media.mediaText + ' {\n';
|
||||||
@ -365,7 +361,7 @@ export class ShadowCss {
|
|||||||
if (isPresent(rule.cssText)) {
|
if (isPresent(rule.cssText)) {
|
||||||
cssText += rule.cssText + '\n\n';
|
cssText += rule.cssText + '\n\n';
|
||||||
}
|
}
|
||||||
} catch(x) {
|
} catch (x) {
|
||||||
if (DOM.isKeyframesRule(rule) && isPresent(rule.cssRules)) {
|
if (DOM.isKeyframesRule(rule) && isPresent(rule.cssRules)) {
|
||||||
cssText += this._ieSafeCssTextFromKeyFrameRule(rule);
|
cssText += this._ieSafeCssTextFromKeyFrameRule(rule);
|
||||||
}
|
}
|
||||||
@ -387,15 +383,15 @@ export class ShadowCss {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_scopeSelector(selector: string, scopeSelector: string, hostSelector: string,
|
_scopeSelector(selector: string, scopeSelector: string, hostSelector: string,
|
||||||
strict: boolean): string {
|
strict: boolean): string {
|
||||||
var r = [], parts = selector.split(',');
|
var r = [], parts = selector.split(',');
|
||||||
for (var i = 0; i < parts.length; i++) {
|
for (var i = 0; i < parts.length; i++) {
|
||||||
var p = parts[i];
|
var p = parts[i];
|
||||||
p = p.trim();
|
p = p.trim();
|
||||||
if (this._selectorNeedsScoping(p, scopeSelector)) {
|
if (this._selectorNeedsScoping(p, scopeSelector)) {
|
||||||
p = strict && !StringWrapper.contains(p, _polyfillHostNoCombinator) ?
|
p = strict && !StringWrapper.contains(p, _polyfillHostNoCombinator) ?
|
||||||
this._applyStrictSelectorScope(p, scopeSelector) :
|
this._applyStrictSelectorScope(p, scopeSelector) :
|
||||||
this._applySelectorScope(p, scopeSelector, hostSelector);
|
this._applySelectorScope(p, scopeSelector, hostSelector);
|
||||||
}
|
}
|
||||||
ListWrapper.push(r, p);
|
ListWrapper.push(r, p);
|
||||||
}
|
}
|
||||||
@ -436,26 +432,23 @@ export class ShadowCss {
|
|||||||
_applyStrictSelectorScope(selector: string, scopeSelector: string): string {
|
_applyStrictSelectorScope(selector: string, scopeSelector: string): string {
|
||||||
var isRe = RegExpWrapper.create('\\[is=([^\\]]*)\\]');
|
var isRe = RegExpWrapper.create('\\[is=([^\\]]*)\\]');
|
||||||
scopeSelector = StringWrapper.replaceAllMapped(scopeSelector, isRe, (m) => m[1]);
|
scopeSelector = StringWrapper.replaceAllMapped(scopeSelector, isRe, (m) => m[1]);
|
||||||
var splits = [' ', '>', '+', '~'],
|
var splits = [' ', '>', '+', '~'], scoped = selector, attrName = '[' + scopeSelector + ']';
|
||||||
scoped = selector,
|
|
||||||
attrName = '[' + scopeSelector + ']';
|
|
||||||
for (var i = 0; i < splits.length; i++) {
|
for (var i = 0; i < splits.length; i++) {
|
||||||
var sep = splits[i];
|
var sep = splits[i];
|
||||||
var parts = scoped.split(sep);
|
var parts = scoped.split(sep);
|
||||||
scoped = ListWrapper.map(parts, function(p) {
|
scoped = ListWrapper.map(parts, function(p) {
|
||||||
// remove :host since it should be unnecessary
|
// remove :host since it should be unnecessary
|
||||||
var t = StringWrapper.replaceAll(p.trim(), _polyfillHostRe, '');
|
var t = StringWrapper.replaceAll(p.trim(), _polyfillHostRe, '');
|
||||||
if (t.length > 0 &&
|
if (t.length > 0 && !ListWrapper.contains(splits, t) &&
|
||||||
!ListWrapper.contains(splits, t) &&
|
!StringWrapper.contains(t, attrName)) {
|
||||||
!StringWrapper.contains(t, attrName)) {
|
var re = RegExpWrapper.create('([^:]*)(:*)(.*)');
|
||||||
var re = RegExpWrapper.create('([^:]*)(:*)(.*)');
|
var m = RegExpWrapper.firstMatch(re, t);
|
||||||
var m = RegExpWrapper.firstMatch(re, t);
|
if (isPresent(m)) {
|
||||||
if (isPresent(m)) {
|
p = m[1] + attrName + m[2] + m[3];
|
||||||
p = m[1] + attrName + m[2] + m[3];
|
}
|
||||||
}
|
}
|
||||||
}
|
return p;
|
||||||
return p;
|
}).join(sep);
|
||||||
}).join(sep);
|
|
||||||
}
|
}
|
||||||
return scoped;
|
return scoped;
|
||||||
}
|
}
|
||||||
@ -475,8 +468,8 @@ export class ShadowCss {
|
|||||||
if (rule.style.content.length > 0 &&
|
if (rule.style.content.length > 0 &&
|
||||||
!isPresent(RegExpWrapper.firstMatch(attrRe, rule.style.content))) {
|
!isPresent(RegExpWrapper.firstMatch(attrRe, rule.style.content))) {
|
||||||
var contentRe = RegExpWrapper.create('content:[^;]*;');
|
var contentRe = RegExpWrapper.create('content:[^;]*;');
|
||||||
cssText = StringWrapper.replaceAll(cssText, contentRe, 'content: \'' +
|
cssText =
|
||||||
rule.style.content + '\';');
|
StringWrapper.replaceAll(cssText, contentRe, 'content: \'' + rule.style.content + '\';');
|
||||||
}
|
}
|
||||||
// TODO(sorvell): we can workaround this issue here, but we need a list
|
// TODO(sorvell): we can workaround this issue here, but we need a list
|
||||||
// of troublesome properties to fix https://github.com/Polymer/platform/issues/53
|
// of troublesome properties to fix https://github.com/Polymer/platform/issues/53
|
||||||
@ -484,8 +477,8 @@ export class ShadowCss {
|
|||||||
// inherit rules can be omitted from cssText
|
// inherit rules can be omitted from cssText
|
||||||
// TODO(sorvell): remove when Blink bug is fixed:
|
// TODO(sorvell): remove when Blink bug is fixed:
|
||||||
// https://code.google.com/p/chromium/issues/detail?id=358273
|
// https://code.google.com/p/chromium/issues/detail?id=358273
|
||||||
//var style = rule.style;
|
// var style = rule.style;
|
||||||
//for (var i = 0; i < style.length; i++) {
|
// for (var i = 0; i < style.length; i++) {
|
||||||
// var name = style.item(i);
|
// var name = style.item(i);
|
||||||
// var value = style.getPropertyValue(name);
|
// var value = style.getPropertyValue(name);
|
||||||
// if (value == 'initial') {
|
// if (value == 'initial') {
|
||||||
@ -497,11 +490,11 @@ export class ShadowCss {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _cssContentNextSelectorRe = RegExpWrapper.create(
|
var _cssContentNextSelectorRe = RegExpWrapper.create(
|
||||||
'polyfill-next-selector[^}]*content:[\\s]*?[\'"](.*?)[\'"][;\\s]*}([^{]*?){', 'im');
|
'polyfill-next-selector[^}]*content:[\\s]*?[\'"](.*?)[\'"][;\\s]*}([^{]*?){', 'im');
|
||||||
var _cssContentRuleRe = RegExpWrapper.create(
|
var _cssContentRuleRe =
|
||||||
'(polyfill-rule)[^}]*(content:[\\s]*[\'"](.*?)[\'"])[;\\s]*[^}]*}', 'im');
|
RegExpWrapper.create('(polyfill-rule)[^}]*(content:[\\s]*[\'"](.*?)[\'"])[;\\s]*[^}]*}', 'im');
|
||||||
var _cssContentUnscopedRuleRe = RegExpWrapper.create(
|
var _cssContentUnscopedRuleRe = RegExpWrapper.create(
|
||||||
'(polyfill-unscoped-rule)[^}]*(content:[\\s]*[\'"](.*?)[\'"])[;\\s]*[^}]*}', 'im');
|
'(polyfill-unscoped-rule)[^}]*(content:[\\s]*[\'"](.*?)[\'"])[;\\s]*[^}]*}', 'im');
|
||||||
var _polyfillHost = '-shadowcsshost';
|
var _polyfillHost = '-shadowcsshost';
|
||||||
// note: :host-context pre-processed to -shadowcsshostcontext.
|
// note: :host-context pre-processed to -shadowcsshostcontext.
|
||||||
var _polyfillHostContext = '-shadowcsscontext';
|
var _polyfillHostContext = '-shadowcsscontext';
|
||||||
@ -516,9 +509,9 @@ var _shadowDOMSelectorsRe = [
|
|||||||
RegExpWrapper.create('::shadow'),
|
RegExpWrapper.create('::shadow'),
|
||||||
RegExpWrapper.create('::content'),
|
RegExpWrapper.create('::content'),
|
||||||
// Deprecated selectors
|
// Deprecated selectors
|
||||||
RegExpWrapper.create('/deep/'), // former >>>
|
RegExpWrapper.create('/deep/'), // former >>>
|
||||||
RegExpWrapper.create('/shadow-deep/'), // former /deep/
|
RegExpWrapper.create('/shadow-deep/'), // former /deep/
|
||||||
RegExpWrapper.create('/shadow/'), // former ::shadow
|
RegExpWrapper.create('/shadow/'), // former ::shadow
|
||||||
];
|
];
|
||||||
var _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$';
|
var _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$';
|
||||||
var _polyfillHostRe = RegExpWrapper.create(_polyfillHost, 'im');
|
var _polyfillHostRe = RegExpWrapper.create(_polyfillHost, 'im');
|
@ -10,19 +10,19 @@ import {CompileControl} from '../compiler/compile_control';
|
|||||||
import {ViewDefinition} from '../../api';
|
import {ViewDefinition} from '../../api';
|
||||||
import {ShadowDomStrategy} from './shadow_dom_strategy';
|
import {ShadowDomStrategy} from './shadow_dom_strategy';
|
||||||
|
|
||||||
export class ShadowDomCompileStep extends CompileStep {
|
export class ShadowDomCompileStep implements CompileStep {
|
||||||
_shadowDomStrategy: ShadowDomStrategy;
|
_shadowDomStrategy: ShadowDomStrategy;
|
||||||
_template: ViewDefinition;
|
_template: ViewDefinition;
|
||||||
_subTaskPromises: List<Promise>;
|
_subTaskPromises: List<Promise<any>>;
|
||||||
|
|
||||||
constructor(shadowDomStrategy: ShadowDomStrategy, template: ViewDefinition, subTaskPromises:List<Promise>) {
|
constructor(shadowDomStrategy: ShadowDomStrategy, template: ViewDefinition,
|
||||||
super();
|
subTaskPromises: List<Promise<any>>) {
|
||||||
this._shadowDomStrategy = shadowDomStrategy;
|
this._shadowDomStrategy = shadowDomStrategy;
|
||||||
this._template = template;
|
this._template = template;
|
||||||
this._subTaskPromises = subTaskPromises;
|
this._subTaskPromises = subTaskPromises;
|
||||||
}
|
}
|
||||||
|
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent: CompileElement, current: CompileElement, control: CompileControl) {
|
||||||
var tagName = DOM.tagName(current.element).toUpperCase();
|
var tagName = DOM.tagName(current.element).toUpperCase();
|
||||||
if (tagName == 'STYLE') {
|
if (tagName == 'STYLE') {
|
||||||
this._processStyleElement(current, control);
|
this._processStyleElement(current, control);
|
||||||
@ -30,16 +30,14 @@ export class ShadowDomCompileStep extends CompileStep {
|
|||||||
this._processContentElement(current);
|
this._processContentElement(current);
|
||||||
} else {
|
} else {
|
||||||
var componentId = current.isBound() ? current.inheritedElementBinder.componentId : null;
|
var componentId = current.isBound() ? current.inheritedElementBinder.componentId : null;
|
||||||
this._shadowDomStrategy.processElement(
|
this._shadowDomStrategy.processElement(this._template.componentId, componentId,
|
||||||
this._template.componentId, componentId, current.element
|
current.element);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_processStyleElement(current:CompileElement, control:CompileControl) {
|
_processStyleElement(current: CompileElement, control: CompileControl) {
|
||||||
var stylePromise = this._shadowDomStrategy.processStyleElement(
|
var stylePromise = this._shadowDomStrategy.processStyleElement(
|
||||||
this._template.componentId, this._template.absUrl, current.element
|
this._template.componentId, this._template.absUrl, current.element);
|
||||||
);
|
|
||||||
if (isPresent(stylePromise) && PromiseWrapper.isPromise(stylePromise)) {
|
if (isPresent(stylePromise) && PromiseWrapper.isPromise(stylePromise)) {
|
||||||
ListWrapper.push(this._subTaskPromises, stylePromise);
|
ListWrapper.push(this._subTaskPromises, stylePromise);
|
||||||
}
|
}
|
||||||
@ -49,7 +47,7 @@ export class ShadowDomCompileStep extends CompileStep {
|
|||||||
control.ignoreCurrentElement();
|
control.ignoreCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
_processContentElement(current:CompileElement) {
|
_processContentElement(current: CompileElement) {
|
||||||
if (this._shadowDomStrategy.hasNativeContentElement()) {
|
if (this._shadowDomStrategy.hasNativeContentElement()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
@ -5,30 +5,24 @@ import * as viewModule from '../view/view';
|
|||||||
import {LightDom} from './light_dom';
|
import {LightDom} from './light_dom';
|
||||||
|
|
||||||
export class ShadowDomStrategy {
|
export class ShadowDomStrategy {
|
||||||
hasNativeContentElement():boolean {
|
hasNativeContentElement(): boolean { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares and returns the shadow root for the given element.
|
* Prepares and returns the shadow root for the given element.
|
||||||
*/
|
*/
|
||||||
prepareShadowRoot(el):any {
|
prepareShadowRoot(el): any { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructLightDom(lightDomView:viewModule.DomView, el): LightDom {
|
constructLightDom(lightDomView: viewModule.DomView, el): LightDom { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An optional step that can modify the template style elements.
|
* An optional step that can modify the template style elements.
|
||||||
*/
|
*/
|
||||||
processStyleElement(hostComponentId:string, templateUrl:string, styleElement):Promise {
|
processStyleElement(hostComponentId: string, templateUrl: string, styleElement): Promise<any> {
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An optional step that can modify the template elements (style elements exlcuded).
|
* An optional step that can modify the template elements (style elements exlcuded).
|
||||||
*/
|
*/
|
||||||
processElement(hostComponentId:string, elementComponentId:string, element) {}
|
processElement(hostComponentId: string, elementComponentId: string, element) {}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
import {Injectable} from 'angular2/di';
|
||||||
import {XHR} from 'angular2/src/services/xhr';
|
import {XHR} from 'angular2/src/services/xhr';
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
@ -18,6 +18,10 @@ import {
|
|||||||
PromiseWrapper,
|
PromiseWrapper,
|
||||||
} from 'angular2/src/facade/async';
|
} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
|
export class SyncAsyncResult<T> {
|
||||||
|
constructor(public syncResult: T, public asyncResult: Promise<T>) {}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inline @import rules in the given CSS.
|
* Inline @import rules in the given CSS.
|
||||||
*
|
*
|
||||||
@ -44,19 +48,18 @@ export class StyleInliner {
|
|||||||
* @param {string} baseUrl
|
* @param {string} baseUrl
|
||||||
* @returns {*} a Promise<string> when @import rules are present, a string otherwise
|
* @returns {*} a Promise<string> when @import rules are present, a string otherwise
|
||||||
*/
|
*/
|
||||||
// TODO(vicb): Union types: returns either a Promise<string> or a string
|
inlineImports(cssText: string, baseUrl: string): SyncAsyncResult<string> {
|
||||||
// TODO(vicb): commented out @import rules should not be inlined
|
|
||||||
inlineImports(cssText: string, baseUrl: string) {
|
|
||||||
return this._inlineImports(cssText, baseUrl, []);
|
return this._inlineImports(cssText, baseUrl, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
_inlineImports(cssText: string, baseUrl: string, inlinedUrls: List<string>) {
|
_inlineImports(cssText: string, baseUrl: string,
|
||||||
|
inlinedUrls: List<string>): SyncAsyncResult<string> {
|
||||||
var partIndex = 0;
|
var partIndex = 0;
|
||||||
var parts = StringWrapper.split(cssText, _importRe);
|
var parts = StringWrapper.split(cssText, _importRe);
|
||||||
|
|
||||||
if (parts.length === 1) {
|
if (parts.length === 1) {
|
||||||
// no @import rule found, return the original css
|
// no @import rule found, return the original css
|
||||||
return cssText;
|
return new SyncAsyncResult(cssText, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
var promises = [];
|
var promises = [];
|
||||||
@ -81,36 +84,32 @@ export class StyleInliner {
|
|||||||
promise = PromiseWrapper.resolve(prefix);
|
promise = PromiseWrapper.resolve(prefix);
|
||||||
} else {
|
} else {
|
||||||
ListWrapper.push(inlinedUrls, url);
|
ListWrapper.push(inlinedUrls, url);
|
||||||
promise = PromiseWrapper.then(
|
promise = PromiseWrapper.then(this._xhr.get(url), (rawCss) => {
|
||||||
this._xhr.get(url),
|
// resolve nested @import rules
|
||||||
(css) => {
|
var inlinedCss = this._inlineImports(rawCss, url, inlinedUrls);
|
||||||
// resolve nested @import rules
|
if (isPresent(inlinedCss.asyncResult)) {
|
||||||
css = this._inlineImports(css, url, inlinedUrls);
|
// wait until nested @import are inlined
|
||||||
if (PromiseWrapper.isPromise(css)) {
|
return inlinedCss.asyncResult.then(
|
||||||
// wait until nested @import are inlined
|
(css) => {return prefix + this._transformImportedCss(css, mediaQuery, url) + '\n'});
|
||||||
return css.then((css) => {
|
} else {
|
||||||
return prefix + this._transformImportedCss(css, mediaQuery, url) + '\n'
|
// there are no nested @import, return the css
|
||||||
}) ;
|
return prefix + this._transformImportedCss(inlinedCss.syncResult, mediaQuery, url) +
|
||||||
} else {
|
'\n';
|
||||||
// there are no nested @import, return the css
|
}
|
||||||
return prefix + this._transformImportedCss(css, mediaQuery, url) + '\n';
|
}, (error) => `/* failed to import ${url} */\n`);
|
||||||
}
|
|
||||||
},
|
|
||||||
(error) => `/* failed to import ${url} */\n`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
ListWrapper.push(promises, promise);
|
ListWrapper.push(promises, promise);
|
||||||
partIndex += 2;
|
partIndex += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PromiseWrapper.all(promises).then(function (cssParts) {
|
return new SyncAsyncResult(null, PromiseWrapper.all(promises).then(function(cssParts) {
|
||||||
var cssText = cssParts.join('');
|
var cssText = cssParts.join('');
|
||||||
if (partIndex < parts.length) {
|
if (partIndex < parts.length) {
|
||||||
// append then content located after the last @import rule
|
// append then content located after the last @import rule
|
||||||
cssText += parts[partIndex];
|
cssText += parts[partIndex];
|
||||||
}
|
}
|
||||||
return cssText;
|
return cssText;
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
_transformImportedCss(css: string, mediaQuery: string, url: string): string {
|
_transformImportedCss(css: string, mediaQuery: string, url: string): string {
|
||||||
@ -134,7 +133,7 @@ function _extractMediaQuery(importRule: string): string {
|
|||||||
var match = RegExpWrapper.firstMatch(_mediaQueryRe, importRule);
|
var match = RegExpWrapper.firstMatch(_mediaQueryRe, importRule);
|
||||||
if (isBlank(match)) return null;
|
if (isBlank(match)) return null;
|
||||||
var mediaQuery = match[1].trim();
|
var mediaQuery = match[1].trim();
|
||||||
return (mediaQuery.length > 0) ? mediaQuery: null;
|
return (mediaQuery.length > 0) ? mediaQuery : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps the css in a media rule when the media query is not null
|
// Wraps the css in a media rule when the media query is not null
|
||||||
@ -144,7 +143,7 @@ function _wrapInMediaRule(css: string, query: string): string {
|
|||||||
|
|
||||||
var _importRe = RegExpWrapper.create('@import\\s+([^;]+);');
|
var _importRe = RegExpWrapper.create('@import\\s+([^;]+);');
|
||||||
var _urlRe = RegExpWrapper.create(
|
var _urlRe = RegExpWrapper.create(
|
||||||
'url\\(\\s*?[\'"]?([^\'")]+)[\'"]?|' + // url(url) or url('url') or url("url")
|
'url\\(\\s*?[\'"]?([^\'")]+)[\'"]?|' + // url(url) or url('url') or url("url")
|
||||||
'[\'"]([^\'")]+)[\'"]' // "url" or 'url'
|
'[\'"]([^\'")]+)[\'"]' // "url" or 'url'
|
||||||
);
|
);
|
||||||
var _mediaQueryRe = RegExpWrapper.create('[\'"][^\'"]+[\'"]\\s*\\)?\\s*(.*)');
|
var _mediaQueryRe = RegExpWrapper.create('[\'"][^\'"]+[\'"]\\s*\\)?\\s*(.*)');
|
@ -1,7 +1,7 @@
|
|||||||
// Some of the code comes from WebComponents.JS
|
// Some of the code comes from WebComponents.JS
|
||||||
// https://github.com/webcomponents/webcomponentsjs/blob/master/src/HTMLImports/path.js
|
// https://github.com/webcomponents/webcomponentsjs/blob/master/src/HTMLImports/path.js
|
||||||
|
|
||||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
import {Injectable} from 'angular2/di';
|
||||||
import {RegExp, RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
import {RegExp, RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||||
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
import {UrlResolver} from 'angular2/src/services/url_resolver';
|
||||||
|
|
||||||
@ -12,9 +12,7 @@ import {UrlResolver} from 'angular2/src/services/url_resolver';
|
|||||||
export class StyleUrlResolver {
|
export class StyleUrlResolver {
|
||||||
_resolver: UrlResolver;
|
_resolver: UrlResolver;
|
||||||
|
|
||||||
constructor(resolver: UrlResolver) {
|
constructor(resolver: UrlResolver) { this._resolver = resolver; }
|
||||||
this._resolver = resolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolveUrls(cssText: string, baseUrl: string) {
|
resolveUrls(cssText: string, baseUrl: string) {
|
||||||
cssText = this._replaceUrls(cssText, _cssUrlRe, baseUrl);
|
cssText = this._replaceUrls(cssText, _cssUrlRe, baseUrl);
|
@ -8,14 +8,12 @@ export const EVENT_TARGET_SEPARATOR = ':';
|
|||||||
var CAMEL_CASE_REGEXP = RegExpWrapper.create('([A-Z])');
|
var CAMEL_CASE_REGEXP = RegExpWrapper.create('([A-Z])');
|
||||||
var DASH_CASE_REGEXP = RegExpWrapper.create('-([a-z])');
|
var DASH_CASE_REGEXP = RegExpWrapper.create('-([a-z])');
|
||||||
|
|
||||||
export function camelCaseToDashCase(input:string) {
|
export function camelCaseToDashCase(input: string) {
|
||||||
return StringWrapper.replaceAllMapped(input, CAMEL_CASE_REGEXP, (m) => {
|
return StringWrapper.replaceAllMapped(input, CAMEL_CASE_REGEXP,
|
||||||
return '-' + m[1].toLowerCase();
|
(m) => { return '-' + m[1].toLowerCase(); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function dashCaseToCamelCase(input:string) {
|
export function dashCaseToCamelCase(input: string) {
|
||||||
return StringWrapper.replaceAllMapped(input, DASH_CASE_REGEXP, (m) => {
|
return StringWrapper.replaceAllMapped(input, DASH_CASE_REGEXP,
|
||||||
return m[1].toUpperCase();
|
(m) => { return m[1].toUpperCase(); });
|
||||||
});
|
}
|
||||||
}
|
|
@ -11,8 +11,8 @@ export class ElementBinder {
|
|||||||
localEvents: List<Event>;
|
localEvents: List<Event>;
|
||||||
globalEvents: List<Event>;
|
globalEvents: List<Event>;
|
||||||
componentId: string;
|
componentId: string;
|
||||||
parentIndex:number;
|
parentIndex: number;
|
||||||
distanceToParent:number;
|
distanceToParent: number;
|
||||||
propertySetters: Map<string, SetterFn>;
|
propertySetters: Map<string, SetterFn>;
|
||||||
hostActions: Map<string, AST>;
|
hostActions: Map<string, AST>;
|
||||||
|
|
||||||
@ -28,6 +28,18 @@ export class ElementBinder {
|
|||||||
parentIndex,
|
parentIndex,
|
||||||
distanceToParent,
|
distanceToParent,
|
||||||
propertySetters
|
propertySetters
|
||||||
|
}:{
|
||||||
|
contentTagSelector?: string,
|
||||||
|
textNodeIndices?: List<number>,
|
||||||
|
nestedProtoView?: protoViewModule.DomProtoView,
|
||||||
|
eventLocals?: AST,
|
||||||
|
localEvents?: List<Event>,
|
||||||
|
globalEvents?: List<Event>,
|
||||||
|
componentId?: string,
|
||||||
|
parentIndex?:number,
|
||||||
|
distanceToParent?:number,
|
||||||
|
propertySetters?: Map<string, SetterFn>,
|
||||||
|
hostActions?: Map<string, AST>
|
||||||
} = {}) {
|
} = {}) {
|
||||||
this.textNodeIndices = textNodeIndices;
|
this.textNodeIndices = textNodeIndices;
|
||||||
this.contentTagSelector = contentTagSelector;
|
this.contentTagSelector = contentTagSelector;
|
@ -1,4 +1,12 @@
|
|||||||
import {StringWrapper, RegExpWrapper, BaseException, isPresent, isBlank, isString, stringify} from 'angular2/src/facade/lang';
|
import {
|
||||||
|
StringWrapper,
|
||||||
|
RegExpWrapper,
|
||||||
|
BaseException,
|
||||||
|
isPresent,
|
||||||
|
isBlank,
|
||||||
|
isString,
|
||||||
|
stringify
|
||||||
|
} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {camelCaseToDashCase, dashCaseToCamelCase} from '../util';
|
import {camelCaseToDashCase, dashCaseToCamelCase} from '../util';
|
||||||
@ -7,6 +15,12 @@ import {reflector} from 'angular2/src/reflection/reflection';
|
|||||||
const STYLE_SEPARATOR = '.';
|
const STYLE_SEPARATOR = '.';
|
||||||
var propertySettersCache = StringMapWrapper.create();
|
var propertySettersCache = StringMapWrapper.create();
|
||||||
var innerHTMLSetterCache;
|
var innerHTMLSetterCache;
|
||||||
|
const ATTRIBUTE_PREFIX = 'attr.';
|
||||||
|
var attributeSettersCache = StringMapWrapper.create();
|
||||||
|
const CLASS_PREFIX = 'class.';
|
||||||
|
var classSettersCache = StringMapWrapper.create();
|
||||||
|
const STYLE_PREFIX = 'style.';
|
||||||
|
var styleSettersCache = StringMapWrapper.create();
|
||||||
|
|
||||||
export function setterFactory(property: string): Function {
|
export function setterFactory(property: string): Function {
|
||||||
var setterFn, styleParts, styleSuffix;
|
var setterFn, styleParts, styleSuffix;
|
||||||
@ -20,7 +34,7 @@ export function setterFactory(property: string): Function {
|
|||||||
setterFn = styleSetterFactory(ListWrapper.get(styleParts, 1), styleSuffix);
|
setterFn = styleSetterFactory(ListWrapper.get(styleParts, 1), styleSuffix);
|
||||||
} else if (StringWrapper.equals(property, 'innerHtml')) {
|
} else if (StringWrapper.equals(property, 'innerHtml')) {
|
||||||
if (isBlank(innerHTMLSetterCache)) {
|
if (isBlank(innerHTMLSetterCache)) {
|
||||||
innerHTMLSetterCache = (el, value) => DOM.setInnerHTML(el, value);
|
innerHTMLSetterCache = (el, value) => DOM.setInnerHTML(el, value);
|
||||||
}
|
}
|
||||||
setterFn = innerHTMLSetterCache;
|
setterFn = innerHTMLSetterCache;
|
||||||
} else {
|
} else {
|
||||||
@ -39,10 +53,7 @@ export function setterFactory(property: string): Function {
|
|||||||
return setterFn;
|
return setterFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ATTRIBUTE_PREFIX = 'attr.';
|
function _isValidAttributeValue(attrName: string, value: any): boolean {
|
||||||
var attributeSettersCache = StringMapWrapper.create();
|
|
||||||
|
|
||||||
function _isValidAttributeValue(attrName:string, value: any): boolean {
|
|
||||||
if (attrName == "role") {
|
if (attrName == "role") {
|
||||||
return isString(value);
|
return isString(value);
|
||||||
} else {
|
} else {
|
||||||
@ -50,7 +61,7 @@ function _isValidAttributeValue(attrName:string, value: any): boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function attributeSetterFactory(attrName:string): Function {
|
function attributeSetterFactory(attrName: string): Function {
|
||||||
var setterFn = StringMapWrapper.get(attributeSettersCache, attrName);
|
var setterFn = StringMapWrapper.get(attributeSettersCache, attrName);
|
||||||
var dashCasedAttributeName;
|
var dashCasedAttributeName;
|
||||||
|
|
||||||
@ -62,7 +73,8 @@ function attributeSetterFactory(attrName:string): Function {
|
|||||||
} else {
|
} else {
|
||||||
if (isPresent(value)) {
|
if (isPresent(value)) {
|
||||||
throw new BaseException("Invalid " + dashCasedAttributeName +
|
throw new BaseException("Invalid " + dashCasedAttributeName +
|
||||||
" attribute, only string values are allowed, got '" + stringify(value) + "'");
|
" attribute, only string values are allowed, got '" +
|
||||||
|
stringify(value) + "'");
|
||||||
}
|
}
|
||||||
DOM.removeAttribute(element, dashCasedAttributeName);
|
DOM.removeAttribute(element, dashCasedAttributeName);
|
||||||
}
|
}
|
||||||
@ -73,10 +85,7 @@ function attributeSetterFactory(attrName:string): Function {
|
|||||||
return setterFn;
|
return setterFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CLASS_PREFIX = 'class.';
|
function classSetterFactory(className: string): Function {
|
||||||
var classSettersCache = StringMapWrapper.create();
|
|
||||||
|
|
||||||
function classSetterFactory(className:string): Function {
|
|
||||||
var setterFn = StringMapWrapper.get(classSettersCache, className);
|
var setterFn = StringMapWrapper.get(classSettersCache, className);
|
||||||
var dashCasedClassName;
|
var dashCasedClassName;
|
||||||
if (isBlank(setterFn)) {
|
if (isBlank(setterFn)) {
|
||||||
@ -94,10 +103,7 @@ function classSetterFactory(className:string): Function {
|
|||||||
return setterFn;
|
return setterFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const STYLE_PREFIX = 'style.';
|
function styleSetterFactory(styleName: string, styleSuffix: string): Function {
|
||||||
var styleSettersCache = StringMapWrapper.create();
|
|
||||||
|
|
||||||
function styleSetterFactory(styleName:string, styleSuffix:string): Function {
|
|
||||||
var cacheKey = styleName + styleSuffix;
|
var cacheKey = styleName + styleSuffix;
|
||||||
var setterFn = StringMapWrapper.get(styleSettersCache, cacheKey);
|
var setterFn = StringMapWrapper.get(styleSettersCache, cacheKey);
|
||||||
var dashCasedStyleName;
|
var dashCasedStyleName;
|
||||||
@ -119,7 +125,7 @@ function styleSetterFactory(styleName:string, styleSuffix:string): Function {
|
|||||||
return setterFn;
|
return setterFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolvePropertyName(attrName:string): string {
|
function resolvePropertyName(attrName: string): string {
|
||||||
var mappedPropName = StringMapWrapper.get(DOM.attrToPropMap, attrName);
|
var mappedPropName = StringMapWrapper.get(DOM.attrToPropMap, attrName);
|
||||||
return isPresent(mappedPropName) ? mappedPropName : attrName;
|
return isPresent(mappedPropName) ? mappedPropName : attrName;
|
||||||
}
|
}
|
@ -8,14 +8,13 @@ import {NG_BINDING_CLASS} from '../util';
|
|||||||
|
|
||||||
import {RenderProtoViewRef} from '../../api';
|
import {RenderProtoViewRef} from '../../api';
|
||||||
|
|
||||||
export function resolveInternalDomProtoView(protoViewRef:RenderProtoViewRef) {
|
export function resolveInternalDomProtoView(protoViewRef: RenderProtoViewRef) {
|
||||||
var domProtoViewRef:DomProtoViewRef = protoViewRef;
|
return (<DomProtoViewRef>protoViewRef)._protoView;
|
||||||
return domProtoViewRef._protoView;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DomProtoViewRef extends RenderProtoViewRef {
|
export class DomProtoViewRef extends RenderProtoViewRef {
|
||||||
_protoView:DomProtoView;
|
_protoView: DomProtoView;
|
||||||
constructor(protoView:DomProtoView) {
|
constructor(protoView: DomProtoView) {
|
||||||
super();
|
super();
|
||||||
this._protoView = protoView;
|
this._protoView = protoView;
|
||||||
}
|
}
|
||||||
@ -23,17 +22,15 @@ export class DomProtoViewRef extends RenderProtoViewRef {
|
|||||||
|
|
||||||
export class DomProtoView {
|
export class DomProtoView {
|
||||||
element;
|
element;
|
||||||
elementBinders:List<ElementBinder>;
|
elementBinders: List<ElementBinder>;
|
||||||
isTemplateElement:boolean;
|
isTemplateElement: boolean;
|
||||||
rootBindingOffset:int;
|
rootBindingOffset: number;
|
||||||
|
|
||||||
constructor({
|
constructor({elementBinders, element}) {
|
||||||
elementBinders,
|
|
||||||
element
|
|
||||||
}) {
|
|
||||||
this.element = element;
|
this.element = element;
|
||||||
this.elementBinders = elementBinders;
|
this.elementBinders = elementBinders;
|
||||||
this.isTemplateElement = DOM.isTemplateElement(this.element);
|
this.isTemplateElement = DOM.isTemplateElement(this.element);
|
||||||
this.rootBindingOffset = (isPresent(this.element) && DOM.hasClass(this.element, NG_BINDING_CLASS)) ? 1 : 0;
|
this.rootBindingOffset =
|
||||||
|
(isPresent(this.element) && DOM.hasClass(this.element, NG_BINDING_CLASS)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,12 @@ import {ListWrapper, MapWrapper, Set, SetWrapper, List} from 'angular2/src/facad
|
|||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ASTWithSource, AST, AstTransformer, AccessMember, LiteralArray, ImplicitReceiver
|
ASTWithSource,
|
||||||
|
AST,
|
||||||
|
AstTransformer,
|
||||||
|
AccessMember,
|
||||||
|
LiteralArray,
|
||||||
|
ImplicitReceiver
|
||||||
} from 'angular2/change_detection';
|
} from 'angular2/change_detection';
|
||||||
|
|
||||||
import {DomProtoView, DomProtoViewRef, resolveInternalDomProtoView} from './proto_view';
|
import {DomProtoView, DomProtoViewRef, resolveInternalDomProtoView} from './proto_view';
|
||||||
@ -17,17 +22,17 @@ import {NG_BINDING_CLASS, EVENT_TARGET_SEPARATOR} from '../util';
|
|||||||
export class ProtoViewBuilder {
|
export class ProtoViewBuilder {
|
||||||
rootElement;
|
rootElement;
|
||||||
variableBindings: Map<string, string>;
|
variableBindings: Map<string, string>;
|
||||||
elements:List<ElementBinderBuilder>;
|
elements: List<ElementBinderBuilder>;
|
||||||
type:number;
|
type: number;
|
||||||
|
|
||||||
constructor(rootElement, type:number) {
|
constructor(rootElement, type: number) {
|
||||||
this.rootElement = rootElement;
|
this.rootElement = rootElement;
|
||||||
this.elements = [];
|
this.elements = [];
|
||||||
this.variableBindings = MapWrapper.create();
|
this.variableBindings = MapWrapper.create();
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bindElement(element, description = null):ElementBinderBuilder {
|
bindElement(element, description = null): ElementBinderBuilder {
|
||||||
var builder = new ElementBinderBuilder(this.elements.length, element, description);
|
var builder = new ElementBinderBuilder(this.elements.length, element, description);
|
||||||
ListWrapper.push(this.elements, builder);
|
ListWrapper.push(this.elements, builder);
|
||||||
DOM.addClass(element, NG_BINDING_CLASS);
|
DOM.addClass(element, NG_BINDING_CLASS);
|
||||||
@ -37,14 +42,15 @@ export class ProtoViewBuilder {
|
|||||||
|
|
||||||
bindVariable(name, value) {
|
bindVariable(name, value) {
|
||||||
// Store the variable map from value to variable, reflecting how it will be used later by
|
// Store the variable map from value to variable, reflecting how it will be used later by
|
||||||
// DomView. When a local is set to the view, a lookup for the variable name will take place keyed
|
// DomView. When a local is set to the view, a lookup for the variable name will take place
|
||||||
|
// keyed
|
||||||
// by the "value", or exported identifier. For example, ng-for sets a view local of "index".
|
// by the "value", or exported identifier. For example, ng-for sets a view local of "index".
|
||||||
// When this occurs, a lookup keyed by "index" must occur to find if there is a var referencing
|
// When this occurs, a lookup keyed by "index" must occur to find if there is a var referencing
|
||||||
// it.
|
// it.
|
||||||
MapWrapper.set(this.variableBindings, value, name);
|
MapWrapper.set(this.variableBindings, value, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
build():api.ProtoViewDto {
|
build(): api.ProtoViewDto {
|
||||||
var renderElementBinders = [];
|
var renderElementBinders = [];
|
||||||
|
|
||||||
var apiElementBinders = [];
|
var apiElementBinders = [];
|
||||||
@ -75,37 +81,39 @@ export class ProtoViewBuilder {
|
|||||||
MapWrapper.set(propertySetters, propertyName, setterFactory(propertyName));
|
MapWrapper.set(propertySetters, propertyName, setterFactory(propertyName));
|
||||||
});
|
});
|
||||||
|
|
||||||
var nestedProtoView =
|
var nestedProtoView = isPresent(ebb.nestedProtoView) ? ebb.nestedProtoView.build() : null;
|
||||||
isPresent(ebb.nestedProtoView) ? ebb.nestedProtoView.build() : null;
|
|
||||||
var parentIndex = isPresent(ebb.parent) ? ebb.parent.index : -1;
|
var parentIndex = isPresent(ebb.parent) ? ebb.parent.index : -1;
|
||||||
ListWrapper.push(apiElementBinders, new api.ElementBinder({
|
ListWrapper.push(apiElementBinders, new api.ElementBinder({
|
||||||
index: ebb.index, parentIndex:parentIndex, distanceToParent:ebb.distanceToParent,
|
index: ebb.index,
|
||||||
|
parentIndex: parentIndex,
|
||||||
|
distanceToParent: ebb.distanceToParent,
|
||||||
directives: apiDirectiveBinders,
|
directives: apiDirectiveBinders,
|
||||||
nestedProtoView: nestedProtoView,
|
nestedProtoView: nestedProtoView,
|
||||||
propertyBindings: ebb.propertyBindings, variableBindings: ebb.variableBindings,
|
propertyBindings: ebb.propertyBindings,
|
||||||
|
variableBindings: ebb.variableBindings,
|
||||||
eventBindings: ebb.eventBindings,
|
eventBindings: ebb.eventBindings,
|
||||||
textBindings: ebb.textBindings,
|
textBindings: ebb.textBindings,
|
||||||
readAttributes: ebb.readAttributes
|
readAttributes: ebb.readAttributes
|
||||||
}));
|
}));
|
||||||
ListWrapper.push(renderElementBinders, new ElementBinder({
|
ListWrapper.push(renderElementBinders, new ElementBinder({
|
||||||
textNodeIndices: ebb.textBindingIndices,
|
textNodeIndices: ebb.textBindingIndices,
|
||||||
contentTagSelector: ebb.contentTagSelector,
|
contentTagSelector: ebb.contentTagSelector,
|
||||||
parentIndex: parentIndex,
|
parentIndex: parentIndex,
|
||||||
distanceToParent: ebb.distanceToParent,
|
distanceToParent: ebb.distanceToParent,
|
||||||
nestedProtoView: isPresent(nestedProtoView) ? resolveInternalDomProtoView(nestedProtoView.render) : null,
|
nestedProtoView: isPresent(nestedProtoView) ?
|
||||||
componentId: ebb.componentId,
|
resolveInternalDomProtoView(nestedProtoView.render) :
|
||||||
eventLocals: new LiteralArray(ebb.eventBuilder.buildEventLocals()),
|
null,
|
||||||
localEvents: ebb.eventBuilder.buildLocalEvents(),
|
componentId: ebb.componentId,
|
||||||
globalEvents: ebb.eventBuilder.buildGlobalEvents(),
|
eventLocals: new LiteralArray(ebb.eventBuilder.buildEventLocals()),
|
||||||
hostActions: hostActions,
|
localEvents: ebb.eventBuilder.buildLocalEvents(),
|
||||||
propertySetters: propertySetters
|
globalEvents: ebb.eventBuilder.buildGlobalEvents(),
|
||||||
}));
|
hostActions: hostActions,
|
||||||
|
propertySetters: propertySetters
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
return new api.ProtoViewDto({
|
return new api.ProtoViewDto({
|
||||||
render: new DomProtoViewRef(new DomProtoView({
|
render: new DomProtoViewRef(
|
||||||
element: this.rootElement,
|
new DomProtoView({element: this.rootElement, elementBinders: renderElementBinders})),
|
||||||
elementBinders: renderElementBinders
|
|
||||||
})),
|
|
||||||
type: this.type,
|
type: this.type,
|
||||||
elementBinders: apiElementBinders,
|
elementBinders: apiElementBinders,
|
||||||
variableBindings: this.variableBindings
|
variableBindings: this.variableBindings
|
||||||
@ -115,18 +123,18 @@ export class ProtoViewBuilder {
|
|||||||
|
|
||||||
export class ElementBinderBuilder {
|
export class ElementBinderBuilder {
|
||||||
element;
|
element;
|
||||||
index:number;
|
index: number;
|
||||||
parent:ElementBinderBuilder;
|
parent: ElementBinderBuilder;
|
||||||
distanceToParent:number;
|
distanceToParent: number;
|
||||||
directives:List<DirectiveBuilder>;
|
directives: List<DirectiveBuilder>;
|
||||||
nestedProtoView:ProtoViewBuilder;
|
nestedProtoView: ProtoViewBuilder;
|
||||||
propertyBindings: Map<string, ASTWithSource>;
|
propertyBindings: Map<string, ASTWithSource>;
|
||||||
variableBindings: Map<string, string>;
|
variableBindings: Map<string, string>;
|
||||||
eventBindings: List<api.EventBinding>;
|
eventBindings: List<api.EventBinding>;
|
||||||
eventBuilder: EventBuilder;
|
eventBuilder: EventBuilder;
|
||||||
textBindingIndices: List<number>;
|
textBindingIndices: List<number>;
|
||||||
textBindings: List<ASTWithSource>;
|
textBindings: List<ASTWithSource>;
|
||||||
contentTagSelector:string;
|
contentTagSelector: string;
|
||||||
readAttributes: Map<string, string>;
|
readAttributes: Map<string, string>;
|
||||||
componentId: string;
|
componentId: string;
|
||||||
|
|
||||||
@ -148,7 +156,7 @@ export class ElementBinderBuilder {
|
|||||||
this.readAttributes = MapWrapper.create();
|
this.readAttributes = MapWrapper.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
setParent(parent:ElementBinderBuilder, distanceToParent):ElementBinderBuilder {
|
setParent(parent: ElementBinderBuilder, distanceToParent): ElementBinderBuilder {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
if (isPresent(parent)) {
|
if (isPresent(parent)) {
|
||||||
this.distanceToParent = distanceToParent;
|
this.distanceToParent = distanceToParent;
|
||||||
@ -156,19 +164,19 @@ export class ElementBinderBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
readAttribute(attrName:string) {
|
readAttribute(attrName: string) {
|
||||||
if (isBlank(MapWrapper.get(this.readAttributes, attrName))) {
|
if (isBlank(MapWrapper.get(this.readAttributes, attrName))) {
|
||||||
MapWrapper.set(this.readAttributes, attrName, DOM.getAttribute(this.element, attrName));
|
MapWrapper.set(this.readAttributes, attrName, DOM.getAttribute(this.element, attrName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindDirective(directiveIndex:number):DirectiveBuilder {
|
bindDirective(directiveIndex: number): DirectiveBuilder {
|
||||||
var directive = new DirectiveBuilder(directiveIndex);
|
var directive = new DirectiveBuilder(directiveIndex);
|
||||||
ListWrapper.push(this.directives, directive);
|
ListWrapper.push(this.directives, directive);
|
||||||
return directive;
|
return directive;
|
||||||
}
|
}
|
||||||
|
|
||||||
bindNestedProtoView(rootElement):ProtoViewBuilder {
|
bindNestedProtoView(rootElement): ProtoViewBuilder {
|
||||||
if (isPresent(this.nestedProtoView)) {
|
if (isPresent(this.nestedProtoView)) {
|
||||||
throw new BaseException('Only one nested view per element is allowed');
|
throw new BaseException('Only one nested view per element is allowed');
|
||||||
}
|
}
|
||||||
@ -179,8 +187,8 @@ export class ElementBinderBuilder {
|
|||||||
bindProperty(name, expression) {
|
bindProperty(name, expression) {
|
||||||
MapWrapper.set(this.propertyBindings, name, expression);
|
MapWrapper.set(this.propertyBindings, name, expression);
|
||||||
|
|
||||||
//TODO: required for Dart transformers. Remove when Dart transformers
|
// TODO: required for Dart transformers. Remove when Dart transformers
|
||||||
//run all the steps of the render compiler
|
// run all the steps of the render compiler
|
||||||
setterFactory(name);
|
setterFactory(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,9 +200,11 @@ export class ElementBinderBuilder {
|
|||||||
this.nestedProtoView.bindVariable(name, value);
|
this.nestedProtoView.bindVariable(name, value);
|
||||||
} else {
|
} else {
|
||||||
// Store the variable map from value to variable, reflecting how it will be used later by
|
// Store the variable map from value to variable, reflecting how it will be used later by
|
||||||
// DomView. When a local is set to the view, a lookup for the variable name will take place keyed
|
// DomView. When a local is set to the view, a lookup for the variable name will take place
|
||||||
|
// keyed
|
||||||
// by the "value", or exported identifier. For example, ng-for sets a view local of "index".
|
// by the "value", or exported identifier. For example, ng-for sets a view local of "index".
|
||||||
// When this occurs, a lookup keyed by "index" must occur to find if there is a var referencing
|
// When this occurs, a lookup keyed by "index" must occur to find if there is a var
|
||||||
|
// referencing
|
||||||
// it.
|
// it.
|
||||||
MapWrapper.set(this.variableBindings, value, name);
|
MapWrapper.set(this.variableBindings, value, name);
|
||||||
}
|
}
|
||||||
@ -209,17 +219,13 @@ export class ElementBinderBuilder {
|
|||||||
ListWrapper.push(this.textBindings, expression);
|
ListWrapper.push(this.textBindings, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentTagSelector(value:string) {
|
setContentTagSelector(value: string) { this.contentTagSelector = value; }
|
||||||
this.contentTagSelector = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
setComponentId(componentId:string) {
|
setComponentId(componentId: string) { this.componentId = componentId; }
|
||||||
this.componentId = componentId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DirectiveBuilder {
|
export class DirectiveBuilder {
|
||||||
directiveIndex:number;
|
directiveIndex: number;
|
||||||
propertyBindings: Map<string, ASTWithSource>;
|
propertyBindings: Map<string, ASTWithSource>;
|
||||||
hostPropertyBindings: Map<string, ASTWithSource>;
|
hostPropertyBindings: Map<string, ASTWithSource>;
|
||||||
hostActions: List<HostAction>;
|
hostActions: List<HostAction>;
|
||||||
@ -235,15 +241,13 @@ export class DirectiveBuilder {
|
|||||||
this.eventBuilder = new EventBuilder();
|
this.eventBuilder = new EventBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindProperty(name, expression) {
|
bindProperty(name, expression) { MapWrapper.set(this.propertyBindings, name, expression); }
|
||||||
MapWrapper.set(this.propertyBindings, name, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
bindHostProperty(name, expression) {
|
bindHostProperty(name, expression) {
|
||||||
MapWrapper.set(this.hostPropertyBindings, name, expression);
|
MapWrapper.set(this.hostPropertyBindings, name, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
bindHostAction(actionName:string, actionExpression:string, expression:ASTWithSource) {
|
bindHostAction(actionName: string, actionExpression: string, expression: ASTWithSource) {
|
||||||
ListWrapper.push(this.hostActions, new HostAction(actionName, actionExpression, expression));
|
ListWrapper.push(this.hostActions, new HostAction(actionName, actionExpression, expression));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +276,8 @@ export class EventBuilder extends AstTransformer {
|
|||||||
// var adjustedAst = astWithSource.ast.visit(this);
|
// var adjustedAst = astWithSource.ast.visit(this);
|
||||||
var adjustedAst = source.ast;
|
var adjustedAst = source.ast;
|
||||||
var fullName = isPresent(target) ? target + EVENT_TARGET_SEPARATOR + name : name;
|
var fullName = isPresent(target) ? target + EVENT_TARGET_SEPARATOR + name : name;
|
||||||
var result = new api.EventBinding(fullName, new ASTWithSource(adjustedAst, source.source, source.location));
|
var result = new api.EventBinding(
|
||||||
|
fullName, new ASTWithSource(adjustedAst, source.source, source.location));
|
||||||
var event = new Event(name, target, fullName);
|
var event = new Event(name, target, fullName);
|
||||||
if (isBlank(target)) {
|
if (isBlank(target)) {
|
||||||
ListWrapper.push(this.localEvents, event);
|
ListWrapper.push(this.localEvents, event);
|
||||||
@ -282,14 +287,15 @@ export class EventBuilder extends AstTransformer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
visitAccessMember(ast:AccessMember) {
|
visitAccessMember(ast: AccessMember) {
|
||||||
var isEventAccess = false;
|
var isEventAccess = false;
|
||||||
var current = ast;
|
var current: AST = ast;
|
||||||
while (!isEventAccess && (current instanceof AccessMember)) {
|
while (!isEventAccess && (current instanceof AccessMember)) {
|
||||||
if (current.name == '$event') {
|
var am = <AccessMember>current;
|
||||||
|
if (am.name == '$event') {
|
||||||
isEventAccess = true;
|
isEventAccess = true;
|
||||||
}
|
}
|
||||||
current = current.receiver;
|
current = am.receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isEventAccess) {
|
if (isEventAccess) {
|
||||||
@ -301,17 +307,11 @@ export class EventBuilder extends AstTransformer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildEventLocals() {
|
buildEventLocals() { return this.locals; }
|
||||||
return this.locals;
|
|
||||||
}
|
|
||||||
|
|
||||||
buildLocalEvents() {
|
buildLocalEvents() { return this.localEvents; }
|
||||||
return this.localEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
buildGlobalEvents() {
|
buildGlobalEvents() { return this.globalEvents; }
|
||||||
return this.globalEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
merge(eventBuilder: EventBuilder) {
|
merge(eventBuilder: EventBuilder) {
|
||||||
this._merge(this.localEvents, eventBuilder.localEvents);
|
this._merge(this.localEvents, eventBuilder.localEvents);
|
@ -8,19 +8,15 @@ import {DomProtoView} from './proto_view';
|
|||||||
import {LightDom} from '../shadow_dom/light_dom';
|
import {LightDom} from '../shadow_dom/light_dom';
|
||||||
import {Content} from '../shadow_dom/content_tag';
|
import {Content} from '../shadow_dom/content_tag';
|
||||||
|
|
||||||
import {RenderViewRef} from '../../api';
|
import {RenderViewRef, EventDispatcher} from '../../api';
|
||||||
|
|
||||||
// TODO(tbosch): enable this again!
|
export function resolveInternalDomView(viewRef: RenderViewRef) {
|
||||||
// import {EventDispatcher} from '../../api';
|
return (<DomViewRef>viewRef)._view;
|
||||||
|
|
||||||
export function resolveInternalDomView(viewRef:RenderViewRef) {
|
|
||||||
var domViewRef:DomViewRef = viewRef;
|
|
||||||
return domViewRef._view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DomViewRef extends RenderViewRef {
|
export class DomViewRef extends RenderViewRef {
|
||||||
_view:DomView;
|
_view: DomView;
|
||||||
constructor(view:DomView) {
|
constructor(view: DomView) {
|
||||||
super();
|
super();
|
||||||
this._view = view;
|
this._view = view;
|
||||||
}
|
}
|
||||||
@ -33,32 +29,20 @@ const NG_BINDING_CLASS = 'ng-binding';
|
|||||||
* Const of making objects: http://jsperf.com/instantiate-size-of-object
|
* Const of making objects: http://jsperf.com/instantiate-size-of-object
|
||||||
*/
|
*/
|
||||||
export class DomView {
|
export class DomView {
|
||||||
boundElements:List;
|
|
||||||
boundTextNodes:List;
|
|
||||||
/// When the view is part of render tree, the DocumentFragment is empty, which is why we need
|
|
||||||
/// to keep track of the nodes.
|
|
||||||
rootNodes:List;
|
|
||||||
// TODO(tbosch): move componentChildViews, viewContainers, contentTags, lightDoms into
|
// TODO(tbosch): move componentChildViews, viewContainers, contentTags, lightDoms into
|
||||||
// a single array with records inside
|
// a single array with records inside
|
||||||
viewContainers: List<DomViewContainer>;
|
viewContainers: List<DomViewContainer>;
|
||||||
contentTags: List<Content>;
|
|
||||||
lightDoms: List<LightDom>;
|
lightDoms: List<LightDom>;
|
||||||
hostLightDom: LightDom;
|
hostLightDom: LightDom;
|
||||||
shadowRoot;
|
shadowRoot;
|
||||||
proto: DomProtoView;
|
|
||||||
hydrated: boolean;
|
hydrated: boolean;
|
||||||
eventDispatcher: any/*EventDispatcher*/;
|
eventDispatcher: EventDispatcher;
|
||||||
eventHandlerRemovers: List<Function>;
|
eventHandlerRemovers: List<Function>;
|
||||||
|
|
||||||
constructor(
|
constructor(public proto: DomProtoView, public rootNodes: List</*node*/ any>,
|
||||||
proto:DomProtoView, rootNodes:List,
|
public boundTextNodes: List</*node*/ any>,
|
||||||
boundTextNodes: List, boundElements:List, contentTags:List) {
|
public boundElements: List</*element*/ any>, public contentTags: List<Content>) {
|
||||||
this.proto = proto;
|
|
||||||
this.rootNodes = rootNodes;
|
|
||||||
this.boundTextNodes = boundTextNodes;
|
|
||||||
this.boundElements = boundElements;
|
|
||||||
this.viewContainers = ListWrapper.createFixedSize(boundElements.length);
|
this.viewContainers = ListWrapper.createFixedSize(boundElements.length);
|
||||||
this.contentTags = contentTags;
|
|
||||||
this.lightDoms = ListWrapper.createFixedSize(boundElements.length);
|
this.lightDoms = ListWrapper.createFixedSize(boundElements.length);
|
||||||
this.hostLightDom = null;
|
this.hostLightDom = null;
|
||||||
this.hydrated = false;
|
this.hydrated = false;
|
||||||
@ -67,7 +51,7 @@ export class DomView {
|
|||||||
this.shadowRoot = null;
|
this.shadowRoot = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDirectParentLightDom(boundElementIndex:number) {
|
getDirectParentLightDom(boundElementIndex: number) {
|
||||||
var binder = this.proto.elementBinders[boundElementIndex];
|
var binder = this.proto.elementBinders[boundElementIndex];
|
||||||
var destLightDom = null;
|
var destLightDom = null;
|
||||||
if (binder.parentIndex !== -1 && binder.distanceToParent === 1) {
|
if (binder.parentIndex !== -1 && binder.distanceToParent === 1) {
|
||||||
@ -76,26 +60,25 @@ export class DomView {
|
|||||||
return destLightDom;
|
return destLightDom;
|
||||||
}
|
}
|
||||||
|
|
||||||
setElementProperty(elementIndex:number, propertyName:string, value:any) {
|
setElementProperty(elementIndex: number, propertyName: string, value: any) {
|
||||||
var setter = MapWrapper.get(this.proto.elementBinders[elementIndex].propertySetters, propertyName);
|
var setter =
|
||||||
|
MapWrapper.get(this.proto.elementBinders[elementIndex].propertySetters, propertyName);
|
||||||
setter(this.boundElements[elementIndex], value);
|
setter(this.boundElements[elementIndex], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
callAction(elementIndex:number, actionExpression:string, actionArgs:any) {
|
callAction(elementIndex: number, actionExpression: string, actionArgs: any) {
|
||||||
var binder = this.proto.elementBinders[elementIndex];
|
var binder = this.proto.elementBinders[elementIndex];
|
||||||
var hostAction = MapWrapper.get(binder.hostActions, actionExpression);
|
var hostAction = MapWrapper.get(binder.hostActions, actionExpression);
|
||||||
hostAction.eval(this.boundElements[elementIndex], this._localsWithAction(actionArgs));
|
hostAction.eval(this.boundElements[elementIndex], this._localsWithAction(actionArgs));
|
||||||
}
|
}
|
||||||
|
|
||||||
_localsWithAction(action:Object):Locals {
|
_localsWithAction(action: Object): Locals {
|
||||||
var map = MapWrapper.create();
|
var map = MapWrapper.create();
|
||||||
MapWrapper.set(map, '$action', action);
|
MapWrapper.set(map, '$action', action);
|
||||||
return new Locals(null, map);
|
return new Locals(null, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
setText(textIndex:number, value:string) {
|
setText(textIndex: number, value: string) { DOM.setText(this.boundTextNodes[textIndex], value); }
|
||||||
DOM.setText(this.boundTextNodes[textIndex], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatchEvent(elementIndex, eventName, event): boolean {
|
dispatchEvent(elementIndex, eventName, event): boolean {
|
||||||
var allowDefaultBehavior = true;
|
var allowDefaultBehavior = true;
|
||||||
@ -104,9 +87,11 @@ export class DomView {
|
|||||||
MapWrapper.set(evalLocals, '$event', event);
|
MapWrapper.set(evalLocals, '$event', event);
|
||||||
// TODO(tbosch): reenable this when we are parsing element properties
|
// TODO(tbosch): reenable this when we are parsing element properties
|
||||||
// out of action expressions
|
// out of action expressions
|
||||||
// var localValues = this.proto.elementBinders[elementIndex].eventLocals.eval(null, new Locals(null, evalLocals));
|
// var localValues = this.proto.elementBinders[elementIndex].eventLocals.eval(null, new
|
||||||
|
// Locals(null, evalLocals));
|
||||||
// this.eventDispatcher.dispatchEvent(elementIndex, eventName, localValues);
|
// this.eventDispatcher.dispatchEvent(elementIndex, eventName, localValues);
|
||||||
allowDefaultBehavior = this.eventDispatcher.dispatchEvent(elementIndex, eventName, evalLocals);
|
allowDefaultBehavior =
|
||||||
|
this.eventDispatcher.dispatchEvent(elementIndex, eventName, evalLocals);
|
||||||
if (!allowDefaultBehavior) {
|
if (!allowDefaultBehavior) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
@ -10,16 +10,13 @@ export class DomViewContainer {
|
|||||||
this.views = [];
|
this.views = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
contentTagContainers() {
|
contentTagContainers() { return this.views; }
|
||||||
return this.views;
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes():List {
|
nodes(): List</*node*/ any> {
|
||||||
var r = [];
|
var r = [];
|
||||||
for (var i = 0; i < this.views.length; ++i) {
|
for (var i = 0; i < this.views.length; ++i) {
|
||||||
r = ListWrapper.concat(r, this.views[i].rootNodes);
|
r = ListWrapper.concat(r, this.views[i].rootNodes);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
12
modules/angular2/src/services/title.js
vendored
12
modules/angular2/src/services/title.js
vendored
@ -1,12 +0,0 @@
|
|||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
|
||||||
|
|
||||||
export class Title {
|
|
||||||
|
|
||||||
getTitle():string {
|
|
||||||
return DOM.getTitle();
|
|
||||||
}
|
|
||||||
|
|
||||||
setTitle(newTitle:string) {
|
|
||||||
DOM.setTitle(newTitle);
|
|
||||||
}
|
|
||||||
}
|
|
7
modules/angular2/src/services/title.ts
Normal file
7
modules/angular2/src/services/title.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
|
export class Title {
|
||||||
|
getTitle(): string { return DOM.getTitle(); }
|
||||||
|
|
||||||
|
setTitle(newTitle: string) { DOM.setTitle(newTitle); }
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
import {Injectable} from 'angular2/di';
|
||||||
import {isPresent, isBlank, RegExpWrapper, BaseException} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, RegExpWrapper, BaseException} from 'angular2/src/facade/lang';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
|
|
||||||
@ -18,15 +18,19 @@ export class UrlResolver {
|
|||||||
* ## When the `baseUrl` is null
|
* ## When the `baseUrl` is null
|
||||||
*
|
*
|
||||||
* `url` is resolved in the context of the current document.
|
* `url` is resolved in the context of the current document.
|
||||||
* If the document location is 'http://www.foo.com/base' and the `url` is 'path/to/here', the resolved url will be
|
* If the document location is 'http://www.foo.com/base' and the `url` is 'path/to/here', the
|
||||||
|
* resolved url will be
|
||||||
* 'http://www.foo.com/base/path/to/here'
|
* 'http://www.foo.com/base/path/to/here'
|
||||||
*
|
*
|
||||||
* ## When the `baseUrl` is not null
|
* ## When the `baseUrl` is not null
|
||||||
*
|
*
|
||||||
* - when the `url` is null, the `baseUrl` is returned,
|
* - when the `url` is null, the `baseUrl` is returned,
|
||||||
* - due to a limitation in the process used to resolve urls (a HTMLLinkElement), `url` must not start with a `/`,
|
* - due to a limitation in the process used to resolve urls (a HTMLLinkElement), `url` must not
|
||||||
* - if `url` is relative ('path/to/here', './path/to/here'), the resolved url is a combination of `baseUrl` and `url`,
|
* start with a `/`,
|
||||||
* - if `url` is absolute (it has a scheme: 'http://', 'https://'), the `url` is returned (ignoring the `baseUrl`)
|
* - if `url` is relative ('path/to/here', './path/to/here'), the resolved url is a combination of
|
||||||
|
* `baseUrl` and `url`,
|
||||||
|
* - if `url` is absolute (it has a scheme: 'http://', 'https://'), the `url` is returned
|
||||||
|
* (ignoring the `baseUrl`)
|
||||||
*
|
*
|
||||||
* @param {string} baseUrl
|
* @param {string} baseUrl
|
||||||
* @param {string} url
|
* @param {string} url
|
||||||
@ -41,10 +45,12 @@ export class UrlResolver {
|
|||||||
if (isBlank(url) || url == '') return baseUrl;
|
if (isBlank(url) || url == '') return baseUrl;
|
||||||
|
|
||||||
if (url[0] == '/') {
|
if (url[0] == '/') {
|
||||||
// The `HTMLLinkElement` does not allow resolving this case (the `url` would be interpreted as relative):
|
// The `HTMLLinkElement` does not allow resolving this case (the `url` would be interpreted as
|
||||||
|
// relative):
|
||||||
// - `baseUrl` = 'http://www.foo.com/base'
|
// - `baseUrl` = 'http://www.foo.com/base'
|
||||||
// - `url` = '/absolute/path/to/here'
|
// - `url` = '/absolute/path/to/here'
|
||||||
// - the result would be 'http://www.foo.com/base/absolute/path/to/here' while 'http://www.foo.com/absolute/path/to/here'
|
// - the result would be 'http://www.foo.com/base/absolute/path/to/here' while
|
||||||
|
// 'http://www.foo.com/absolute/path/to/here'
|
||||||
// is expected (without the 'base' segment).
|
// is expected (without the 'base' segment).
|
||||||
throw new BaseException(`Could not resolve the url ${url} from ${baseUrl}`);
|
throw new BaseException(`Could not resolve the url ${url} from ${baseUrl}`);
|
||||||
}
|
}
|
@ -1,7 +1,5 @@
|
|||||||
import {Promise} from 'angular2/src/facade/async';
|
import {Promise} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
export class XHR {
|
export class XHR {
|
||||||
get(url: string): Promise<string> {
|
get(url: string): Promise<string> { return null; }
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {Injectable} from 'angular2/src/di/annotations_impl';
|
import {Injectable} from 'angular2/di';
|
||||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
import {XHR} from './xhr';
|
import {XHR} from './xhr';
|
||||||
|
|
||||||
@ -19,9 +19,7 @@ export class XHRImpl extends XHR {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = function() {
|
xhr.onerror = function() { completer.reject(`Failed to load ${url}`); };
|
||||||
completer.reject(`Failed to load ${url}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.send();
|
xhr.send();
|
||||||
return completer.promise;
|
return completer.promise;
|
@ -22,8 +22,7 @@ export function makeDecorator(annotationCls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function makeParamDecorator(annotationCls) {
|
export function makeParamDecorator(annotationCls) {
|
||||||
return function() {
|
return function(... args) {
|
||||||
var args = arguments;
|
|
||||||
var Reflect = global.Reflect;
|
var Reflect = global.Reflect;
|
||||||
if (!(Reflect && Reflect.getMetadata)) {
|
if (!(Reflect && Reflect.getMetadata)) {
|
||||||
throw 'reflect-metadata shim is required when using parameter decorators';
|
throw 'reflect-metadata shim is required when using parameter decorators';
|
||||||
|
@ -183,10 +183,9 @@ class MockStepFactory extends CompileStepFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockStep extends CompileStep {
|
class MockStep /*implements CompileStep*/ {
|
||||||
processClosure:Function;
|
processClosure:Function;
|
||||||
constructor(process) {
|
constructor(process) {
|
||||||
super();
|
|
||||||
this.processClosure = process;
|
this.processClosure = process;
|
||||||
}
|
}
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {describe, beforeEach, it, xit, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
import {describe, beforeEach, it, xit, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
||||||
import {isPresent, isBlank, assertionsEnabled} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, assertionsEnabled, IMPLEMENTS} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {DirectiveParser} from 'angular2/src/render/dom/compiler/directive_parser';
|
import {DirectiveParser} from 'angular2/src/render/dom/compiler/directive_parser';
|
||||||
@ -225,10 +225,10 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockStep extends CompileStep {
|
@IMPLEMENTS(CompileStep)
|
||||||
|
class MockStep {
|
||||||
processClosure:Function;
|
processClosure:Function;
|
||||||
constructor(process) {
|
constructor(process) {
|
||||||
super();
|
|
||||||
this.processClosure = process;
|
this.processClosure = process;
|
||||||
}
|
}
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
||||||
import {ListWrapper, List, MapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, List, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||||
import {isPresent, NumberWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
import {isPresent, NumberWrapper, StringWrapper, IMPLEMENTS} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
||||||
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
||||||
@ -182,10 +182,10 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockStep extends CompileStep {
|
@IMPLEMENTS(CompileStep)
|
||||||
|
class MockStep {
|
||||||
processClosure:Function;
|
processClosure:Function;
|
||||||
constructor(process) {
|
constructor(process) {
|
||||||
super();
|
|
||||||
this.processClosure = process;
|
this.processClosure = process;
|
||||||
}
|
}
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||||
@ -193,7 +193,8 @@ class MockStep extends CompileStep {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IgnoreChildrenStep extends CompileStep {
|
@IMPLEMENTS(CompileStep)
|
||||||
|
export class IgnoreChildrenStep {
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||||
var attributeMap = DOM.attributeMap(current.element);
|
var attributeMap = DOM.attributeMap(current.element);
|
||||||
if (MapWrapper.contains(attributeMap, 'ignore-children')) {
|
if (MapWrapper.contains(attributeMap, 'ignore-children')) {
|
||||||
@ -202,7 +203,8 @@ export class IgnoreChildrenStep extends CompileStep {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IgnoreCurrentElementStep extends CompileStep {
|
@IMPLEMENTS(CompileStep)
|
||||||
|
class IgnoreCurrentElementStep {
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||||
var attributeMap = DOM.attributeMap(current.element);
|
var attributeMap = DOM.attributeMap(current.element);
|
||||||
if (MapWrapper.contains(attributeMap, 'ignore-current')) {
|
if (MapWrapper.contains(attributeMap, 'ignore-current')) {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
import {describe, beforeEach, it, expect, iit, ddescribe, el} from 'angular2/test_lib';
|
||||||
|
import {IMPLEMENTS} from 'angular2/src/facade/lang';
|
||||||
import {PropertyBindingParser} from 'angular2/src/render/dom/compiler/property_binding_parser';
|
import {PropertyBindingParser} from 'angular2/src/render/dom/compiler/property_binding_parser';
|
||||||
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
import {CompilePipeline} from 'angular2/src/render/dom/compiler/compile_pipeline';
|
||||||
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
import {CompileElement} from 'angular2/src/render/dom/compiler/compile_element';
|
||||||
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step'
|
import {CompileStep} from 'angular2/src/render/dom/compiler/compile_step';
|
||||||
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
import {CompileControl} from 'angular2/src/render/dom/compiler/compile_control';
|
||||||
import {Lexer, Parser} from 'angular2/change_detection';
|
import {Lexer, Parser} from 'angular2/change_detection';
|
||||||
|
|
||||||
@ -164,10 +165,10 @@ export function main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockStep extends CompileStep {
|
@IMPLEMENTS(CompileStep)
|
||||||
|
class MockStep {
|
||||||
processClosure:Function;
|
processClosure:Function;
|
||||||
constructor(process) {
|
constructor(process) {
|
||||||
super();
|
|
||||||
this.processClosure = process;
|
this.processClosure = process;
|
||||||
}
|
}
|
||||||
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
|
||||||
|
@ -10,13 +10,12 @@ import {RenderViewRef, ProtoViewDto, ViewDefinition, EventDispatcher, DirectiveM
|
|||||||
import {resolveInternalDomView} from 'angular2/src/render/dom/view/view';
|
import {resolveInternalDomView} from 'angular2/src/render/dom/view/view';
|
||||||
import {el, dispatchEvent} from 'angular2/test_lib';
|
import {el, dispatchEvent} from 'angular2/test_lib';
|
||||||
|
|
||||||
export class TestView extends EventDispatcher {
|
export class TestView {
|
||||||
rawView:DomView;
|
rawView:DomView;
|
||||||
viewRef:RenderViewRef;
|
viewRef:RenderViewRef;
|
||||||
events:List;
|
events:List;
|
||||||
|
|
||||||
constructor(viewRef:RenderViewRef) {
|
constructor(viewRef:RenderViewRef) {
|
||||||
super();
|
|
||||||
this.viewRef = viewRef;
|
this.viewRef = viewRef;
|
||||||
this.rawView = resolveInternalDomView(viewRef);
|
this.rawView = resolveInternalDomView(viewRef);
|
||||||
this.events = [];
|
this.events = [];
|
||||||
@ -24,11 +23,11 @@ export class TestView extends EventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LoggingEventDispatcher extends EventDispatcher {
|
@IMPLEMENTS(EventDispatcher)
|
||||||
|
class LoggingEventDispatcher {
|
||||||
log:List;
|
log:List;
|
||||||
|
|
||||||
constructor(log:List) {
|
constructor(log:List) {
|
||||||
super();
|
|
||||||
this.log = log;
|
this.log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,8 +32,7 @@ export function main() {
|
|||||||
it('should return a string when there is no import statement', inject([StyleInliner], (inliner) => {
|
it('should return a string when there is no import statement', inject([StyleInliner], (inliner) => {
|
||||||
var css = '.main {}';
|
var css = '.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
expect(loadedCss).not.toBePromise();
|
expect(loadedCss.syncResult).toEqual(css);
|
||||||
expect(loadedCss).toEqual(css);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should inline @import rules',
|
it('should inline @import rules',
|
||||||
@ -41,9 +40,9 @@ export function main() {
|
|||||||
xhr.reply('http://base/one.css', '.one {}');
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
var css = '@import url("one.css");.main {}';
|
var css = '@import url("one.css");.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('.one {}\n.main {}');
|
expect(css).toEqual('.one {}\n.main {}');
|
||||||
async.done();
|
async.done();
|
||||||
@ -59,9 +58,9 @@ export function main() {
|
|||||||
xhr.reply('http://base/one.css', '.one {}');
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
var css = '@import url(one.css);.main {}';
|
var css = '@import url(one.css);.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('.one {}\n.main {}');
|
expect(css).toEqual('.one {}\n.main {}');
|
||||||
async.done();
|
async.done();
|
||||||
@ -76,9 +75,9 @@ export function main() {
|
|||||||
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
inject([StyleInliner, AsyncTestCompleter], (inliner, async) => {
|
||||||
var css = '@import "one.css";.main {}';
|
var css = '@import "one.css";.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('/* failed to import http://base/one.css */\n.main {}');
|
expect(css).toEqual('/* failed to import http://base/one.css */\n.main {}');
|
||||||
async.done();
|
async.done();
|
||||||
@ -95,9 +94,9 @@ export function main() {
|
|||||||
xhr.reply('http://base/two.css', '.two {}');
|
xhr.reply('http://base/two.css', '.two {}');
|
||||||
var css = '@import "one.css";@import "two.css";.main {}';
|
var css = '@import "one.css";@import "two.css";.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base');
|
var loadedCss = inliner.inlineImports(css, 'http://base');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('.one {}\n.two {}\n.main {}');
|
expect(css).toEqual('.one {}\n.two {}\n.main {}');
|
||||||
async.done();
|
async.done();
|
||||||
@ -114,9 +113,9 @@ export function main() {
|
|||||||
xhr.reply('http://base/two.css', '.two {}');
|
xhr.reply('http://base/two.css', '.two {}');
|
||||||
var css = '@import "one.css";.main {}';
|
var css = '@import "one.css";.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
||||||
async.done();
|
async.done();
|
||||||
@ -133,9 +132,9 @@ export function main() {
|
|||||||
xhr.reply('http://base/two.css', '@import "one.css";.two {}');
|
xhr.reply('http://base/two.css', '@import "one.css";.two {}');
|
||||||
var css = '@import "one.css";.main {}';
|
var css = '@import "one.css";.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
expect(css).toEqual('.two {}\n.one {}\n.main {}');
|
||||||
async.done();
|
async.done();
|
||||||
@ -151,9 +150,9 @@ export function main() {
|
|||||||
// Invalid rule: the url is not quoted
|
// Invalid rule: the url is not quoted
|
||||||
var css = '@import one.css;.main {}';
|
var css = '@import one.css;.main {}';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('/* Invalid import rule: "@import one.css;" */.main {}');
|
expect(css).toEqual('/* Invalid import rule: "@import one.css;" */.main {}');
|
||||||
async.done();
|
async.done();
|
||||||
@ -171,9 +170,9 @@ export function main() {
|
|||||||
xhr.reply('http://base/one.css', '.one {}');
|
xhr.reply('http://base/one.css', '.one {}');
|
||||||
var css = '@import "one.css" (min-width: 700px) and (orientation: landscape);';
|
var css = '@import "one.css" (min-width: 700px) and (orientation: landscape);';
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual('@media (min-width: 700px) and (orientation: landscape) {\n.one {}\n}\n');
|
expect(css).toEqual('@media (min-width: 700px) and (orientation: landscape) {\n.one {}\n}\n');
|
||||||
async.done();
|
async.done();
|
||||||
@ -193,9 +192,9 @@ export function main() {
|
|||||||
xhr.reply('http://base/nested/two.css', '.two {background-image: url("../img/two.jpg");}');
|
xhr.reply('http://base/nested/two.css', '.two {background-image: url("../img/two.jpg");}');
|
||||||
var css = '@import "one.css";'
|
var css = '@import "one.css";'
|
||||||
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
var loadedCss = inliner.inlineImports(css, 'http://base/');
|
||||||
expect(loadedCss).toBePromise();
|
expect(loadedCss.asyncResult).toBePromise();
|
||||||
PromiseWrapper.then(
|
PromiseWrapper.then(
|
||||||
loadedCss,
|
loadedCss.asyncResult,
|
||||||
function(css) {
|
function(css) {
|
||||||
expect(css).toEqual(
|
expect(css).toEqual(
|
||||||
".two {background-image: url('http://base/img/two.jpg');}\n" +
|
".two {background-image: url('http://base/img/two.jpg');}\n" +
|
||||||
|
@ -21,7 +21,6 @@ module.exports = function makeNodeTree(destinationPath) {
|
|||||||
include: ['angular2/**', 'benchpress/**', 'rtts_assert/**', '**/e2e_test/**'],
|
include: ['angular2/**', 'benchpress/**', 'rtts_assert/**', '**/e2e_test/**'],
|
||||||
exclude: [
|
exclude: [
|
||||||
// the following code and tests are not compatible with CJS/node environment
|
// the following code and tests are not compatible with CJS/node environment
|
||||||
'angular2/src/core/zone/ng_zone.es6',
|
|
||||||
'angular2/test/core/zone/**',
|
'angular2/test/core/zone/**',
|
||||||
'angular2/test/test_lib/fake_async_spec.js'
|
'angular2/test/test_lib/fake_async_spec.js'
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user