chore: remove facades and dart-specific patterns

This commit is contained in:
Jeremy Elbourn
2016-04-06 11:35:17 -07:00
parent e99da663f7
commit 5f398d1435
36 changed files with 127 additions and 1383 deletions
+1 -1
View File
@@ -62,7 +62,7 @@
"symlink-or-copy": "^1.0.1",
"ts-node": "^0.5.5",
"tslint": "^3.5.0",
"typescript": "^1.7.5",
"typescript": "^1.8.0",
"typings": "^0.6.8",
"which": "^1.2.4"
}
+3 -5
View File
@@ -1,13 +1,11 @@
import {
inject,
TestComponentBuilder
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
inject,
TestComponentBuilder
} from 'angular2/testing';
import {Component} from 'angular2/core';
import {By} from 'angular2/platform/browser';
+1 -2
View File
@@ -8,7 +8,6 @@ import {
ElementRef,
Renderer,
} from 'angular2/core';
import {TimerWrapper} from 'angular2/src/facade/async';
// TODO(jelbourn): Ink ripples.
// TODO(jelbourn): Make the `isMouseDown` stuff done with one global listener.
@@ -55,7 +54,7 @@ export class MdButton {
// button continues to look :active after clicking.
// @see http://marcysutton.com/button-focus-hell/
this.isMouseDown = true;
TimerWrapper.setTimeout(() => { this.isMouseDown = false; }, 100);
setTimeout(() => { this.isMouseDown = false; }, 100);
}
_updateColor(newColor: string) {
+2 -2
View File
@@ -1,5 +1,5 @@
import {Component, ViewEncapsulation, ChangeDetectionStrategy} from 'angular2/core';
import {CONST_EXPR} from 'angular2/src/facade/lang';
/*
@@ -71,4 +71,4 @@ TODO(kara): update link to demo site when it exists
})
export class MdCardTitleGroup {}
export const MD_CARD_DIRECTIVES: any[] = CONST_EXPR([MdCard, MdCardHeader, MdCardTitleGroup]);
export const MD_CARD_DIRECTIVES: any[] = [MdCard, MdCardHeader, MdCardTitleGroup];
+4 -8
View File
@@ -1,18 +1,14 @@
import {
it,
describe,
expect,
beforeEach,
fakeAsync,
inject,
tick,
ComponentFixture,
TestComponentBuilder,
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
import {Component, DebugElement, EventEmitter} from 'angular2/core';
import {By} from 'angular2/platform/browser';
+3 -6
View File
@@ -15,9 +15,6 @@ import {
NG_VALUE_ACCESSOR,
ControlValueAccessor
} from 'angular2/src/common/forms/directives/control_value_accessor';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import { OneOf } from '../../core/annotations/one-of';
/**
* Monotonically increasing integer used to auto-generate unique ids for checkbox components.
@@ -28,11 +25,11 @@ let nextId = 0;
* Provider Expression that allows md-checkbox to register as a ControlValueAccessor. This allows it
* to support [(ngModel)] and ngControl.
*/
const MD_CHECKBOX_CONTROL_VALUE_ACCESSOR = CONST_EXPR(new Provider(
const MD_CHECKBOX_CONTROL_VALUE_ACCESSOR = new Provider(
NG_VALUE_ACCESSOR, {
useExisting: forwardRef(() => MdCheckbox),
multi: true
}));
});
/**
* Represents the different states that require custom transitions between them.
@@ -93,7 +90,7 @@ export class MdCheckbox implements ControlValueAccessor {
@Input() id: string = `md-checkbox-${++nextId}`;
/** Whether or not the checkbox should come before or after the label. */
@Input() @OneOf(['start', 'end']) align: string = 'start';
@Input() align: 'start' | 'end' = 'start';
/**
* Whether the checkbox is disabled. When the checkbox is disabled it cannot be interacted with.
+3 -5
View File
@@ -1,4 +1,7 @@
import {
it,
expect,
beforeEach,
fakeAsync,
inject,
ComponentFixture,
@@ -8,11 +11,6 @@ import {
} from 'angular2/testing';
import {Component} from 'angular2/core';
import {By} from 'angular2/platform/browser';
import {
it,
expect,
beforeEach,
} from '../../core/facade/testing';
import {
MdInput,
MdInputDuplicatedHintException,
+11 -11
View File
@@ -12,28 +12,28 @@ import {
QueryList,
OnChanges,
} from 'angular2/core';
import {CONST_EXPR, noop} from 'angular2/src/facade/lang';
import {
NG_VALUE_ACCESSOR,
ControlValueAccessor
} from 'angular2/src/common/forms/directives/control_value_accessor';
import {BaseException} from 'angular2/src/facade/exceptions';
import {BooleanFieldValue} from '../../core/annotations/field-value';
import {OneOf} from '../../core/annotations/one-of';
const MD_INPUT_CONTROL_VALUE_ACCESSOR = CONST_EXPR(new Provider(
const noop = () => {};
const MD_INPUT_CONTROL_VALUE_ACCESSOR = new Provider(
NG_VALUE_ACCESSOR, {
useExisting: forwardRef(() => MdInput),
multi: true
}));
});
// Invalid input type. Using one of these will throw an MdInputUnsupportedTypeException.
const MD_INPUT_INVALID_INPUT_TYPE = CONST_EXPR([
const MD_INPUT_INVALID_INPUT_TYPE = [
'file',
'radio',
'checkbox',
]);
];
let nextUniqueId = 0;
@@ -81,7 +81,7 @@ export class MdPlaceholder {}
})
export class MdHint {
// Whether to align the hint label at the start or end of the line.
@Input() @OneOf(['start', 'end']) align: string;
@Input() align: 'start' | 'end' = 'start';
}
@@ -129,9 +129,9 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
/**
* Bindings.
*/
@Input() @OneOf(['start', 'end']) align: string = 'start';
@Input() align: 'start' | 'end' = 'start';
@Input() dividerColor: 'primary' | 'accent' | 'warn' = 'primary';
@Input() @BooleanFieldValue() disabled: boolean = false;
@Input() @OneOf(['primary', 'accent', 'warn']) dividerColor: string = 'primary';
@Input() @BooleanFieldValue() floatingPlaceholder: boolean = true;
@Input() hintLabel: string = '';
@Input() id: string = `md-input-${nextUniqueId++}`;
@@ -234,8 +234,8 @@ export class MdInput implements ControlValueAccessor, AfterContentInit, OnChange
}
}
export const MD_INPUT_DIRECTIVES: any[] = CONST_EXPR([
export const MD_INPUT_DIRECTIVES: any[] = [
MdPlaceholder,
MdInput,
MdHint,
]);
];
+3 -5
View File
@@ -1,13 +1,11 @@
import {
inject,
TestComponentBuilder
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
inject,
TestComponentBuilder
} from 'angular2/testing';
import {Component} from 'angular2/core';
import {By} from 'angular2/platform/browser';
+1 -2
View File
@@ -1,6 +1,5 @@
import {Component, ViewEncapsulation, ContentChildren, ContentChild, QueryList, Directive,
ElementRef, Renderer, AfterContentInit} from 'angular2/core';
import {CONST_EXPR} from 'angular2/src/facade/lang';
@Component({
selector: 'md-list',
@@ -60,4 +59,4 @@ export class MdListItem implements AfterContentInit {
}
}
export const MD_LIST_DIRECTIVES: any[] = CONST_EXPR([MdList, MdListItem, MdLine, MdListAvatar]);
export const MD_LIST_DIRECTIVES: any[] = [MdList, MdListItem, MdLine, MdListAvatar];
@@ -1,10 +1,10 @@
import {inject, TestComponentBuilder} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
inject,
TestComponentBuilder} from 'angular2/testing';
import {Component, DebugElement} from 'angular2/core';
import {By} from 'angular2/platform/browser';
import {MdProgressCircle} from './progress-circle';
@@ -30,18 +30,6 @@ export function main() {
});
});
it('should apply mode of "determinate" if an invalid mode is provided.', (done: () => void) => {
builder
.overrideTemplate(TestApp, '<md-progress-circle mode="spinny"></md-progress-circle>')
.createAsync(TestApp)
.then((fixture) => {
fixture.detectChanges();
let progressElement = getChildDebugElement(fixture.debugElement, 'md-progress-circle');
expect(progressElement.componentInstance.mode).toBe('determinate');
done();
});
});
it('should not modify the mode if a valid mode is provided.', (done: () => void) => {
builder
.overrideTemplate(TestApp, '<md-progress-circle mode="indeterminate"></md-progress-circle>')
@@ -4,20 +4,10 @@ import {
HostBinding,
Input
} from 'angular2/core';
import {isPresent, CONST} from 'angular2/src/facade/lang';
import {Math} from 'angular2/src/facade/math';
import {OneOf} from '../../core/annotations/one-of';
// TODO(josephperrott): Benchpress tests.
/** Display modes of Progress Circle */
@CONST()
class ProgressMode {
@CONST() static DETERMINATE = 'determinate';
@CONST() static INDETERMINATE = 'indeterminate';
}
/**
* <md-progress-circle> component.
@@ -51,9 +41,7 @@ export class MdProgressCircle {
* mode is bound to the host as the attribute host.
*/
@HostBinding('attr.mode')
@Input()
@OneOf([ProgressMode.DETERMINATE, ProgressMode.INDETERMINATE])
mode: string;
@Input() mode: 'determinate' | 'indeterminate' = 'determinate';
/**
@@ -81,7 +69,7 @@ export class MdProgressCircle {
/** Sets the progress value, clamping before setting the internal value. */
set value(v: number) {
if (isPresent(v)) {
if (v != null) {
this._value = MdProgressCircle.clamp(v);
}
}
@@ -113,6 +101,6 @@ export class MdProgressCircle {
export class MdSpinner extends MdProgressCircle {
constructor() {
super();
this.mode = ProgressMode.INDETERMINATE;
this.mode = 'indeterminate';
}
}
+5 -7
View File
@@ -1,15 +1,13 @@
import {
fakeAsync,
inject,
tick,
TestComponentBuilder
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
fakeAsync,
inject,
tick,
TestComponentBuilder
} from 'angular2/testing';
import {Component, DebugElement} from 'angular2/core';
import {By} from 'angular2/platform/browser';
+2 -3
View File
@@ -20,7 +20,6 @@ import {
NG_VALUE_ACCESSOR,
ControlValueAccessor
} from 'angular2/src/common/forms/directives/control_value_accessor';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {MdRadioDispatcher} from './radio_dispatcher';
export {MdRadioDispatcher} from './radio_dispatcher';
@@ -29,11 +28,11 @@ export {MdRadioDispatcher} from './radio_dispatcher';
* Provider Expression that allows md-radio-group to register as a ControlValueAccessor. This
* allows it to support [(ngModel)] and ngControl.
*/
const MD_RADIO_GROUP_CONTROL_VALUE_ACCESSOR = CONST_EXPR(new Provider(
const MD_RADIO_GROUP_CONTROL_VALUE_ACCESSOR = new Provider(
NG_VALUE_ACCESSOR, {
useExisting: forwardRef(() => MdRadioGroup),
multi: true
}));
});
// TODO(mtlin):
// Ink ripple is currently placeholder.
+4 -9
View File
@@ -1,4 +1,8 @@
import {
it,
describe,
expect,
beforeEach,
ComponentFixture,
TestComponentBuilder,
fakeAsync,
@@ -7,15 +11,6 @@ import {
tick
} from 'angular2/testing';
import {XHR} from 'angular2/src/compiler/xhr';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
import {
getComputedStyle
} from '../../core/facade/html';
import {
Component,
ViewMetadata
+13 -19
View File
@@ -11,14 +11,11 @@ import {
Output,
QueryList,
Type,
ChangeDetectionStrategy
ChangeDetectionStrategy,
EventEmitter,
} from 'angular2/core';
import {PromiseWrapper, ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
import {iterateListLike} from 'angular2/src/facade/collection';
import {BaseException} from 'angular2/src/facade/exceptions';
import {CONST_EXPR, isPresent} from 'angular2/src/facade/lang';
import {Dir} from '../../core/rtl/dir';
import {OneOf} from '../../core/annotations/one-of';
import {PromiseCompleter} from 'angular2/src/facade/promise';
@@ -51,25 +48,25 @@ export class MdDuplicatedSidenavException extends BaseException {
})
export class MdSidenav {
/** Alignment of the sidenav (direction neutral); whether 'start' or 'end'. */
@Input() @OneOf(['start', 'end']) align: string = 'start';
@Input() align: 'start' | 'end' = 'start';
/** Mode of the sidenav; whether 'over' or 'side'. */
@Input() @OneOf(['over', 'push', 'side']) mode: string = 'over';
@Input() mode: 'over' | 'push' | 'side' = 'over';
/** Whether the sidenav is opened. */
@Input('opened') private _opened: boolean;
/** Event emitted when the sidenav is being opened. Use this to synchronize animations. */
@Output('open-start') onOpenStart = new EventEmitter<Object>();
@Output('open-start') onOpenStart = new EventEmitter<void>();
/** Event emitted when the sidenav is fully opened. */
@Output('open') onOpen = new EventEmitter<Object>();
@Output('open') onOpen = new EventEmitter<void>();
/** Event emitted when the sidenav is being closed. Use this to synchronize animations. */
@Output('close-start') onCloseStart = new EventEmitter<Object>();
@Output('close-start') onCloseStart = new EventEmitter<void>();
/** Event emitted when the sidenav is fully closed. */
@Output('close') onClose = new EventEmitter<Object>();
@Output('close') onClose = new EventEmitter<void>();
/**
@@ -107,14 +104,11 @@ export class MdSidenav {
* close() when it's closed.
* @param isOpen
*/
toggle(isOpen?: boolean): Promise<void> {
if (!isPresent(isOpen)) {
isOpen = !this.opened;
}
toggle(isOpen: boolean = !this.opened): Promise<void> {
// Shortcut it if we're already opened.
if (isOpen === this.opened) {
if (!this._transition) {
return PromiseWrapper.resolve(null);
return Promise.resolve();
} else {
return isOpen ? this._openPromise : this._closePromise;
}
@@ -268,7 +262,7 @@ export class MdSidenavLayout implements AfterContentInit {
ngAfterContentInit() {
// On changes, assert on consistency.
ObservableWrapper.subscribe(this._sidenavs.changes, () => this._validateDrawers());
this._sidenavs.changes.subscribe(() => this._validateDrawers());
this._validateDrawers();
}
@@ -297,7 +291,7 @@ export class MdSidenavLayout implements AfterContentInit {
}
// Ensure that we have at most one start and one end sidenav.
iterateListLike(this._sidenavs, (sidenav: any) => {
this._sidenavs.forEach(sidenav => {
if (sidenav.align == 'end') {
if (this._end != null) {
throw new MdDuplicatedSidenavException('end');
@@ -368,4 +362,4 @@ export class MdSidenavLayout implements AfterContentInit {
}
export const MD_SIDENAV_DIRECTIVES: Type[] = CONST_EXPR([MdSidenavLayout, MdSidenav]);
export const MD_SIDENAV_DIRECTIVES: Type[] = [MdSidenavLayout, MdSidenav];
+3 -6
View File
@@ -1,15 +1,12 @@
import {Component} from 'angular2/core';
import {
inject,
TestComponentBuilder
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
inject,
TestComponentBuilder
} from 'angular2/testing';
import {By} from 'angular2/platform/browser';
import {MdToolbar} from './toolbar';
+2 -5
View File
@@ -1,6 +1,3 @@
import {isPresent} from 'angular2/src/facade/lang';
declare var Symbol: any;
@@ -22,13 +19,13 @@ function booleanFieldValueFactory() {
const defaultValue = target[key];
// Use a fallback if Symbol isn't available.
const localKey = isPresent(Symbol) ? Symbol(key) : `__md_private_symbol_${key}`;
const localKey = Symbol ? Symbol(key) : `__md_private_symbol_${key}`;
target[localKey] = defaultValue;
Object.defineProperty(target, key, {
get() { return this[localKey]; },
set(value: boolean) {
this[localKey] = isPresent(value) && value !== null && String(value) != 'false';
this[localKey] = value != null && `${value}` !== 'false';
}
});
};
-33
View File
@@ -1,33 +0,0 @@
import {isPresent} from 'angular2/src/facade/lang';
declare var Symbol: any;
/**
* Annotation Factory that only allows a set of values to be set for a property.
* @param values The list of allowed values. The first value listed will be used as a default if
* the set value isn't part of the list of accepted values.
*/
function oneOfFactory(values: any[]) {
return function oneOfMetadata(target: any, key: string): void {
const defaultValue = values[0];
// Use a fallback if Symbol isn't available.
const localKey = isPresent(Symbol) ? Symbol(key) : `@@$${key}_`;
target[localKey] = defaultValue;
Object.defineProperty(target, key, {
get() { return this[localKey]; },
set(v) {
if (values.indexOf(v) == -1) {
this[localKey] = defaultValue;
} else {
this[localKey] = v;
}
}
});
};
}
export { oneOfFactory as OneOf };
-6
View File
@@ -1,12 +1,6 @@
// RTL
export * from './rtl/dir';
// Annotations
export {OneOf} from './annotations/one-of';
// Portals
export * from './portal/portal';
export * from './portal/portal-directives';
// Facades
export * from './facade/html';
-4
View File
@@ -1,4 +0,0 @@
export function getComputedStyle(element: HTMLElement, pseudoElt?: string) {
return window.getComputedStyle(element, pseudoElt);
}
-157
View File
@@ -1,157 +0,0 @@
import {Injector, Provider, PLATFORM_INITIALIZER} from 'angular2/core';
import {BaseException} from 'angular2/src/facade/exceptions';
import {ListWrapper} from 'angular2/src/facade/collection';
import {FunctionWrapper, isPresent, Type} from 'angular2/src/facade/lang';
export class TestInjector {
private _instantiated: boolean = false;
private _injector: Injector = null;
private _providers: Array<Type | Provider | any[]> = [];
reset() {
this._injector = null;
this._providers = [];
this._instantiated = false;
}
platformProviders: Array<Type | Provider | any[]> = [];
applicationProviders: Array<Type | Provider | any[]> = [];
addProviders(providers: Array<Type | Provider | any[]>) {
if (this._instantiated) {
throw new BaseException('Cannot add providers after test injector is instantiated');
}
this._providers = ListWrapper.concat(this._providers, providers);
}
createInjector() {
let rootInjector = Injector.resolveAndCreate(this.platformProviders);
this._injector = rootInjector.resolveAndCreateChild(
ListWrapper.concat(this.applicationProviders, this._providers));
this._instantiated = true;
return this._injector;
}
execute(fn: FunctionWithParamTokens): any {
if (!this._instantiated) {
this.createInjector();
}
return fn.execute(this._injector);
}
}
let testInjectorCache: TestInjector = null;
export function getTestInjector() {
if (testInjectorCache == null) {
testInjectorCache = new TestInjector();
}
return testInjectorCache;
}
/**
* Set the providers that the test injector should use. These should be providers
* common to every test in the suite.
*
* This may only be called once, to set up the common providers for the current test
* suite on teh current platform. If you absolutely need to change the providers,
* first use `resetBaseTestProviders`.
*
* Test Providers for individual platforms are available from
* 'angular2/platform/testing/<platform_name>'.
*/
export function setBaseTestProviders(platformProviders: Array<Type | Provider | any[]>,
applicationProviders: Array<Type | Provider | any[]>) {
let testInjector = getTestInjector();
if (testInjector.platformProviders.length > 0 || testInjector.applicationProviders.length > 0) {
throw new BaseException('Cannot set base providers because it has already been called');
}
testInjector.platformProviders = platformProviders;
testInjector.applicationProviders = applicationProviders;
let injector = testInjector.createInjector();
let inits: Function[] = <Function[]>injector.getOptional(PLATFORM_INITIALIZER);
if (isPresent(inits)) {
inits.forEach(init => init());
}
testInjector.reset();
}
/**
* Reset the providers for the test injector.
*/
export function resetBaseTestProviders() {
let testInjector = getTestInjector();
testInjector.platformProviders = [];
testInjector.applicationProviders = [];
testInjector.reset();
}
/**
* Allows injecting dependencies in `beforeEach()` and `it()`.
*
* Example:
*
* ```
* beforeEach(inject([Dependency, AClass], (dep, object) => {
* // some code that uses `dep` and `object`
* // ...
* }));
*
* it('...', inject([AClass], (object) => {
* object.doSomething();
* expect(...);
* })
* ```
*
* Notes:
* - inject is currently a function because of some Traceur limitation the syntax should
* eventually
* becomes `it('...', @Inject (object: AClass, async: AsyncTestCompleter) => { ... });`
*
* @param {Array} tokens
* @param {Function} fn
* @return {FunctionWithParamTokens}
*/
export function inject(tokens: any[], fn: Function): FunctionWithParamTokens {
return new FunctionWithParamTokens(tokens, fn, false);
}
/**
* Allows injecting dependencies in `beforeEach()` and `it()`. The test must return
* a promise which will resolve when all asynchronous activity is complete.
*
* Example:
*
* ```
* it('...', injectAsync([AClass], (object) => {
* return object.doSomething().then(() => {
* expect(...);
* });
* })
* ```
*
* @param {Array} tokens
* @param {Function} fn
* @return {FunctionWithParamTokens}
*/
export function injectAsync(tokens: any[], fn: Function): FunctionWithParamTokens {
return new FunctionWithParamTokens(tokens, fn, true);
}
export class FunctionWithParamTokens {
constructor(private _tokens: any[], private _fn: Function, public isAsync: boolean) {}
/**
* Returns the value of the executed function.
*/
execute(injector: Injector): any {
let params = this._tokens.map(t => injector.get(t));
return FunctionWrapper.apply(this._fn, params);
}
hasToken(token: any): boolean { return this._tokens.indexOf(token) > -1; }
}
-8
View File
@@ -1,8 +0,0 @@
export {
it,
iit,
describe,
ddescribe,
expect,
beforeEach,
} from 'angular2/testing';
+3 -5
View File
@@ -1,4 +1,3 @@
import {DOM} from '../platform/dom/dom_adapter';
/**
@@ -6,9 +5,8 @@ import {DOM} from '../platform/dom/dom_adapter';
* with the 'md-overlay-container' class on the document body.
*/
export function createOverlayContainer(): Element {
let documentBody = DOM.getGlobalEventTarget('body');
let container = DOM.createElement('div');
DOM.addClass(container, 'md-overlay-container');
DOM.appendChild(documentBody, container);
let container = document.createElement('div');
container.classList.add('md-overlay-container');
document.body.appendChild(container);
return container;
}
+8 -14
View File
@@ -1,27 +1,23 @@
import {
it,
describe,
expect,
beforeEach,
inject,
TestComponentBuilder,
fakeAsync,
flushMicrotasks,
beforeEachProviders,
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
import {
Component,
ViewChild,
ElementRef,
provide,
} from 'angular2/core';
import {BrowserDomAdapter} from '../platform/browser/browser_adapter';
import {TemplatePortalDirective} from '../portal/portal-directives';
import {TemplatePortal, ComponentPortal} from '../portal/portal';
import {Overlay, OVERLAY_CONTAINER_TOKEN} from './overlay';
import {DOM} from '../platform/dom/dom_adapter';
import {OverlayRef} from './overlay-ref';
import {OverlayState} from './overlay-state';
import {PositionStrategy} from './position/position-strategy';
@@ -29,18 +25,16 @@ import {PositionStrategy} from './position/position-strategy';
export function main() {
describe('Overlay', () => {
BrowserDomAdapter.makeCurrent();
let builder: TestComponentBuilder;
let overlay: Overlay;
let componentPortal: ComponentPortal;
let templatePortal: TemplatePortal;
let overlayContainerElement: Element;
let overlayContainerElement: HTMLElement;
beforeEachProviders(() => [
Overlay,
provide(OVERLAY_CONTAINER_TOKEN, {useFactory: () => {
overlayContainerElement = DOM.createElement('div');
overlayContainerElement = document.createElement('div');
return overlayContainerElement;
}})
]);
@@ -140,7 +134,7 @@ export function main() {
flushMicrotasks();
expect(DOM.querySelectorAll(overlayContainerElement, '.fake-positioned').length).toBe(1);
expect(overlayContainerElement.querySelectorAll('.fake-positioned').length).toBe(1);
}));
});
});
@@ -168,7 +162,7 @@ class TestComponentWithTemplatePortals {
class FakePositionStrategy implements PositionStrategy {
apply(element: Element): Promise<void> {
DOM.addClass(element, 'fake-positioned');
element.classList.add('fake-positioned');
return Promise.resolve();
}
+8 -10
View File
@@ -5,11 +5,9 @@ import {
Inject,
Injectable, ElementRef
} from 'angular2/core';
import {CONST_EXPR} from 'angular2/src/facade/lang';
import {OverlayState} from './overlay-state';
import {DomPortalHost} from '../portal/dom-portal-host';
import {OverlayRef} from './overlay-ref';
import {DOM} from '../platform/dom/dom_adapter';
import {GlobalPositionStrategy} from './position/global-position-strategy';
import {RelativePositionStrategy} from './position/relative-position-strategy';
@@ -20,7 +18,7 @@ export {OverlayRef} from './overlay-ref';
export {createOverlayContainer} from './overlay-container';
/** Token used to inject the DOM element that serves as the overlay container. */
export const OVERLAY_CONTAINER_TOKEN = CONST_EXPR(new OpaqueToken('overlayContainer'));
export const OVERLAY_CONTAINER_TOKEN = new OpaqueToken('overlayContainer');
/** Next overlay unique ID. */
let nextUniqueId = 0;
@@ -40,7 +38,7 @@ let defaultState = new OverlayState();
@Injectable()
export class Overlay {
constructor(
@Inject(OVERLAY_CONTAINER_TOKEN) private _overlayContainerElement: Element,
@Inject(OVERLAY_CONTAINER_TOKEN) private _overlayContainerElement: HTMLElement,
private _dynamicComponentLoader: DynamicComponentLoader,
private _appViewManager: AppViewManager) {
}
@@ -67,10 +65,10 @@ export class Overlay {
* @param state State to apply to the created element.
* @returns Promise resolving to the created element.
*/
private _createPaneElement(state: OverlayState): Promise<Element> {
var pane = DOM.createElement('div');
private _createPaneElement(state: OverlayState): Promise<HTMLElement> {
var pane = document.createElement('div');
pane.id = `md-overlay-${nextUniqueId++}`;
DOM.addClass(pane, 'md-overlay-pane');
pane.classList.add('md-overlay-pane');
this.applyState(pane, state);
this._overlayContainerElement.appendChild(pane);
@@ -83,7 +81,7 @@ export class Overlay {
* @param pane The pane to modify.
* @param state The state to apply.
*/
applyState(pane: Element, state: OverlayState) {
applyState(pane: HTMLElement, state: OverlayState) {
if (state.positionStrategy != null) {
state.positionStrategy.apply(pane);
}
@@ -94,7 +92,7 @@ export class Overlay {
* @param pane The DOM element to turn into a portal host.
* @returns A portal host for the given DOM element.
*/
private _createPortalHost(pane: Element): DomPortalHost {
private _createPortalHost(pane: HTMLElement): DomPortalHost {
return new DomPortalHost(
pane,
this._dynamicComponentLoader,
@@ -106,7 +104,7 @@ export class Overlay {
* @param pane DOM element for the overlay
* @returns {OverlayRef}
*/
private _createOverlayRef(pane: Element): OverlayRef {
private _createOverlayRef(pane: HTMLElement): OverlayRef {
return new OverlayRef(this._createPortalHost(pane));
}
}
@@ -1,27 +1,22 @@
import {
inject,
fakeAsync,
flushMicrotasks,
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../../core/facade/testing';
import {BrowserDomAdapter} from '../../platform/browser/browser_adapter';
import {DOM} from '../../platform/dom/dom_adapter';
inject,
fakeAsync,
flushMicrotasks,
} from 'angular2/testing';
import {GlobalPositionStrategy} from './global-position-strategy';
export function main() {
describe('GlobalPositonStrategy', () => {
BrowserDomAdapter.makeCurrent();
let element: HTMLElement;
let strategy: GlobalPositionStrategy;
beforeEach(() => {
element = DOM.createElement('div');
element = document.createElement('div');
strategy = new GlobalPositionStrategy();
});
@@ -1,5 +1,4 @@
import {PositionStrategy} from './position-strategy';
import {DOM} from '../../platform/dom/dom_adapter';
/**
@@ -86,12 +85,12 @@ export class GlobalPositionStrategy implements PositionStrategy {
}
/** Apply the position to the element. */
apply(element: Element): Promise<void> {
DOM.setStyle(element, 'position', this._cssPosition);
DOM.setStyle(element, 'top', this._top);
DOM.setStyle(element, 'left', this._left);
DOM.setStyle(element, 'bottom', this._bottom);
DOM.setStyle(element, 'right', this._right);
apply(element: HTMLElement): Promise<void> {
element.style.position = this._cssPosition;
element.style.top = this._top;
element.style.left = this._left;
element.style.bottom = this._bottom;
element.style.right = this._right;
// TODO(jelbourn): we don't want to always overwrite the transform property here,
// because it will need to be used for animations.
@@ -100,7 +99,7 @@ export class GlobalPositionStrategy implements PositionStrategy {
// It's important to trim the result, because the browser will ignore the set operation
// if the string contains only whitespace.
DOM.setStyle(element, 'transform', `${tranlateX} ${translateY}`.trim());
element.style.transform = `${tranlateX} ${translateY}`.trim();
return Promise.resolve();
}
@@ -1,622 +0,0 @@
import {ListWrapper} from 'angular2/src/facade/collection';
import {isBlank, isPresent, global, setValueOnPath, DateWrapper} from 'angular2/src/facade/lang';
import {GenericBrowserDomAdapter} from './generic_browser_adapter';
import {setRootDomAdapter} from '../dom/dom_adapter';
var _attrToPropMap: {[key: string]: string} = {
'class': 'className',
'innerHtml': 'innerHTML',
'readonly': 'readOnly',
'tabindex': 'tabIndex'
};
const DOM_KEY_LOCATION_NUMPAD = 3;
// Map to convert some key or keyIdentifier values to what will be returned by getEventKey
var _keyMap: any = {
// The following values are here for cross-browser compatibility and to match the W3C standard
// cf http://www.w3.org/TR/DOM-Level-3-Events-key/
'\b': 'Backspace',
'\t': 'Tab',
'\x7F': 'Delete',
'\x1B': 'Escape',
'Del': 'Delete',
'Esc': 'Escape',
'Left': 'ArrowLeft',
'Right': 'ArrowRight',
'Up': 'ArrowUp',
'Down': 'ArrowDown',
'Menu': 'ContextMenu',
'Scroll': 'ScrollLock',
'Win': 'OS'
};
// There is a bug in Chrome for numeric keypad keys:
// https://code.google.com/p/chromium/issues/detail?id=155654
// 1, 2, 3 ... are reported as A, B, C ...
var _chromeNumKeyPadMap: any = {
'A': '1',
'B': '2',
'C': '3',
'D': '4',
'E': '5',
'F': '6',
'G': '7',
'H': '8',
'I': '9',
'J': '*',
'K': '+',
'M': '-',
'N': '.',
'O': '/',
'\x60': '0',
'\x90': 'NumLock'
};
/**
* A `DomAdapter` powered by full browser DOM APIs.
*/
/* tslint:disable:requireParameterType */
export class BrowserDomAdapter extends GenericBrowserDomAdapter {
parse(templateHtml: string) {
throw new Error('parse not implemented');
}
static makeCurrent() {
setRootDomAdapter(new BrowserDomAdapter());
}
hasProperty(element: any, name: string): boolean {
return name in element;
}
setProperty(el: /*element*/ any, name: string, value: any) {
el[name] = value;
}
getProperty(el: /*element*/ any, name: string): any {
return el[name];
}
invoke(el: /*element*/ any, methodName: string, args: any[]): any {
el[methodName].apply(el, args);
}
// TODO(tbosch): move this into a separate environment class once we have it
logError(error: any) {
if (window.console.error) {
window.console.error(error);
} else {
window.console.log(error);
}
}
log(error: any) {
window.console.log(error);
}
logGroup(error: any) {
if (window.console.group) {
window.console.group(error);
this.logError(error);
} else {
window.console.log(error);
}
}
logGroupEnd() {
if (window.console.groupEnd) {
window.console.groupEnd();
}
}
get _attrToPropMap(): {[key: string]: string} {
return _attrToPropMap;
}
query(selector: string): any {
return document.querySelector(selector);
}
querySelector(el: any, selector: string): HTMLElement {
return el.querySelector(selector);
}
querySelectorAll(el: any, selector: string): any[] {
return el.querySelectorAll(selector);
}
on(el: any, evt: any, listener: any) {
el.addEventListener(evt, listener, false);
}
onAndCancel(el: any, evt: any, listener: any): Function {
el.addEventListener(evt, listener, false);
// Needed to follow Dart's subscription semantic, until fix of
// https://code.google.com/p/dart/issues/detail?id=17406
return () => {
el.removeEventListener(evt, listener, false);
};
}
dispatchEvent(el: any, evt: any) {
el.dispatchEvent(evt);
}
createMouseEvent(eventType: string): MouseEvent {
var evt: MouseEvent = document.createEvent('MouseEvent');
evt.initEvent(eventType, true, true);
return evt;
}
createEvent(eventType: any): Event {
var evt: Event = document.createEvent('Event');
evt.initEvent(eventType, true, true);
return evt;
}
preventDefault(evt: Event) {
evt.preventDefault();
evt.returnValue = false;
}
isPrevented(evt: Event): boolean {
return evt.defaultPrevented || isPresent(evt.returnValue) && !evt.returnValue;
}
getInnerHTML(el: any): string {
return el.innerHTML;
}
getOuterHTML(el: any): string {
return el.outerHTML;
}
nodeName(node: Node): string {
return node.nodeName;
}
nodeValue(node: Node): string {
return node.nodeValue;
}
type(node: HTMLInputElement): string {
return node.type;
}
content(node: Node): Node {
if (this.hasProperty(node, 'content')) {
return (<any>node).content;
} else {
return node;
}
}
firstChild(el: any): Node {
return el.firstChild;
}
nextSibling(el: any): Node {
return el.nextSibling;
}
parentElement(el: any): Node {
return el.parentNode;
}
childNodes(el: any): Node[] {
return el.childNodes;
}
childNodesAsList(el: any): any[] {
var childNodes = el.childNodes;
var res = ListWrapper.createFixedSize(childNodes.length);
for (var i = 0; i < childNodes.length; i++) {
res[i] = childNodes[i];
}
return res;
}
clearNodes(el: any): any {
while (el.firstChild) {
el.removeChild(el.firstChild);
}
}
appendChild(el: any, node: any) {
el.appendChild(node);
}
removeChild(el: any, node: any) {
el.removeChild(node);
}
replaceChild(el: Node, newChild: any, oldChild: any) {
el.replaceChild(newChild, oldChild);
}
remove(node: any): Node {
if (node.parentNode) {
node.parentNode.removeChild(node);
}
return node;
}
insertBefore(el: any, node: any) {
el.parentNode.insertBefore(node, el);
}
insertAllBefore(el: any, nodes: any) {
nodes.forEach((n: any) => el.parentNode.insertBefore(n, el));
}
insertAfter(el: any, node: any) {
el.parentNode.insertBefore(node, el.nextSibling);
}
setInnerHTML(el: any, value: any) {
el.innerHTML = value;
}
getText(el: any): string {
return el.textContent;
}
// TODO(vicb): removed Element type because it does not support StyleElement
setText(el: any, value: string) {
el.textContent = value;
}
getValue(el: any): string {
return el.value;
}
setValue(el: any, value: string) {
el.value = value;
}
getChecked(el: any): boolean {
return el.checked;
}
setChecked(el: any, value: boolean) {
el.checked = value;
}
createComment(text: string): Comment {
return document.createComment(text);
}
createTemplate(html: string): HTMLElement {
var t = document.createElement('template');
t.innerHTML = html;
return t;
}
createElement(tagName: string, doc = document): HTMLElement {
return doc.createElement(tagName);
}
createElementNS(ns: string, tagName: string, doc = document): Element {
return doc.createElementNS(ns, tagName);
}
createTextNode(text: string, doc = document): Text {
return doc.createTextNode(text);
}
createScriptTag(attrName: string, attrValue: string, doc = document): HTMLScriptElement {
var el = <HTMLScriptElement>doc.createElement('SCRIPT');
el.setAttribute(attrName, attrValue);
return el;
}
createStyleElement(css: string, doc = document): HTMLStyleElement {
var style = <HTMLStyleElement>doc.createElement('style');
this.appendChild(style, this.createTextNode(css));
return style;
}
createShadowRoot(el: HTMLElement): DocumentFragment {
return (<any>el).createShadowRoot();
}
getShadowRoot(el: HTMLElement): DocumentFragment {
return (<any>el).shadowRoot;
}
getHost(el: HTMLElement): HTMLElement {
return (<any>el).host;
}
clone(node: Node): Node {
return node.cloneNode(true);
}
getElementsByClassName(element: any, name: string): HTMLElement[] {
return element.getElementsByClassName(name);
}
getElementsByTagName(element: any, name: string): HTMLElement[] {
return element.getElementsByTagName(name);
}
classList(element: any): any[] {
return <any[]>Array.prototype.slice.call(element.classList, 0);
}
addClass(element: any, className: string) {
element.classList.add(className);
}
removeClass(element: any, className: string) {
element.classList.remove(className);
}
hasClass(element: any, className: string): boolean {
return element.classList.contains(className);
}
setStyle(element: any, styleName: string, styleValue: string) {
element.style[styleName] = styleValue;
}
removeStyle(element: any, stylename: string) {
element.style[stylename] = null;
}
getStyle(element: any, stylename: string): string {
return element.style[stylename];
}
hasStyle(element: any, styleName: string, styleValue: string = null): boolean {
var value = this.getStyle(element, styleName) || '';
return styleValue ? value == styleValue : value.length > 0;
}
tagName(element: any): string {
return element.tagName;
}
attributeMap(element: any): Map<string, string> {
var res = new Map<string, string>();
var elAttrs = element.attributes;
for (var i = 0; i < elAttrs.length; i++) {
var attrib = elAttrs[i];
res.set(attrib.name, attrib.value);
}
return res;
}
hasAttribute(element: any, attribute: string): boolean {
return element.hasAttribute(attribute);
}
hasAttributeNS(element: any, ns: string, attribute: string): boolean {
return element.hasAttributeNS(ns, attribute);
}
getAttribute(element: any, attribute: string): string {
return element.getAttribute(attribute);
}
getAttributeNS(element: any, ns: string, name: string): string {
return element.getAttributeNS(ns, name);
}
setAttribute(element: any, name: string, value: string) {
element.setAttribute(name, value);
}
setAttributeNS(element: any, ns: string, name: string, value: string) {
element.setAttributeNS(ns, name, value);
}
removeAttribute(element: any, attribute: string) {
element.removeAttribute(attribute);
}
removeAttributeNS(element: any, ns: string, name: string) {
element.removeAttributeNS(ns, name);
}
templateAwareRoot(el: any): any {
return this.isTemplateElement(el) ? this.content(el) : el;
}
createHtmlDocument(): HTMLDocument {
return document.implementation.createHTMLDocument('fakeTitle');
}
defaultDoc(): HTMLDocument {
return document;
}
getBoundingClientRect(el: any): any {
try {
return el.getBoundingClientRect();
} catch (e) {
return {top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0};
}
}
getTitle(): string {
return document.title;
}
setTitle(newTitle: string) {
document.title = newTitle || '';
}
elementMatches(n: any, selector: string): boolean {
var matches = false;
if (n instanceof HTMLElement) {
if (n.matches) {
matches = n.matches(selector);
} else if (n.msMatchesSelector) {
matches = n.msMatchesSelector(selector);
} else if (n.webkitMatchesSelector) {
matches = n.webkitMatchesSelector(selector);
}
}
return matches;
}
isTemplateElement(el: any): boolean {
return el instanceof HTMLElement && el.nodeName == 'TEMPLATE';
}
isTextNode(node: Node): boolean {
return node.nodeType === Node.TEXT_NODE;
}
isCommentNode(node: Node): boolean {
return node.nodeType === Node.COMMENT_NODE;
}
isElementNode(node: Node): boolean {
return node.nodeType === Node.ELEMENT_NODE;
}
hasShadowRoot(node: any): boolean {
return node instanceof HTMLElement && isPresent(node.shadowRoot);
}
isShadowRoot(node: any): boolean {
return node instanceof DocumentFragment;
}
importIntoDoc(node: Node): any {
var toImport = node;
if (this.isTemplateElement(node)) {
toImport = this.content(node);
}
return document.importNode(toImport, true);
}
adoptNode(node: Node): any {
return document.adoptNode(node);
}
getHref(el: Element): string {
return (<any>el).href;
}
getEventKey(event: any): string {
var key: any = event.key;
if (isBlank(key)) {
key = event.keyIdentifier;
// keyIdentifier is defined in the old draft of DOM Level 3 Events implemented by Chrome and
// Safari
// cf
if (isBlank(key)) {
return 'Unidentified';
}
if (key.startsWith('U+')) {
key = String.fromCharCode(parseInt(key.substring(2), 16));
if (event.location === DOM_KEY_LOCATION_NUMPAD && _chromeNumKeyPadMap.hasOwnProperty(key)) {
// There is a bug in Chrome for numeric keypad keys:
// https://code.google.com/p/chromium/issues/detail?id=155654
// 1, 2, 3 ... are reported as A, B, C ...
key = _chromeNumKeyPadMap[key];
}
}
}
if (_keyMap.hasOwnProperty(key)) {
key = _keyMap[key];
}
return key;
}
getGlobalEventTarget(target: string): EventTarget {
if (target == 'window') {
return window;
} else if (target == 'document') {
return document;
} else if (target == 'body') {
return document.body;
}
}
getHistory(): History {
return window.history;
}
getLocation(): Location {
return window.location;
}
getBaseHref(): string {
var href = getBaseElementHref();
if (isBlank(href)) {
return null;
}
return relativePath(href);
}
resetBaseElement(): void {
baseElement = null;
}
getUserAgent(): string {
return window.navigator.userAgent;
}
setData(element: any, name: string, value: string) {
this.setAttribute(element, 'data-' + name, value);
}
getData(element: any, name: string): string {
return this.getAttribute(element, 'data-' + name);
}
getComputedStyle(element: any): any {
return getComputedStyle(element);
}
// TODO(tbosch): move this into a separate environment class once we have it
setGlobalVar(path: string, value: any) {
setValueOnPath(global, path, value);
}
requestAnimationFrame(callback: any): number {
return window.requestAnimationFrame(callback);
}
cancelAnimationFrame(id: number) {
window.cancelAnimationFrame(id);
}
performanceNow(): number {
// performance.now() is not available in all browsers, see
// http://caniuse.com/#search=performance.now
if (isPresent(window.performance) && isPresent(window.performance.now)) {
return window.performance.now();
} else {
return DateWrapper.toMillis(DateWrapper.now());
}
}
}
var baseElement: any = null;
function getBaseElementHref(): string {
if (isBlank(baseElement)) {
baseElement = document.querySelector('base');
if (isBlank(baseElement)) {
return null;
}
}
return baseElement.getAttribute('href');
}
// based on urlUtils.js in AngularJS 1
var urlParsingNode: any = null;
function relativePath(url: any): string {
if (isBlank(urlParsingNode)) {
urlParsingNode = document.createElement('a');
}
urlParsingNode.setAttribute('href', url);
return (urlParsingNode.pathname.charAt(0) === '/') ? urlParsingNode.pathname :
'/' + urlParsingNode.pathname;
}
@@ -1,77 +0,0 @@
import {StringMapWrapper} from 'angular2/src/facade/collection';
import {isPresent, isFunction, Type} from 'angular2/src/facade/lang';
import {DomAdapter} from 'angular2/src/platform/dom/dom_adapter';
import {XHRImpl} from 'angular2/src/platform/browser/xhr_impl';
/**
* Provides DOM operations in any browser environment.
*/
export abstract class GenericBrowserDomAdapter extends DomAdapter {
private _animationPrefix: string = null;
private _transitionEnd: string = null;
constructor() {
super();
try {
var element = this.createElement('div', this.defaultDoc());
if (isPresent(this.getStyle(element, 'animationName'))) {
this._animationPrefix = '';
} else {
var domPrefixes = ['Webkit', 'Moz', 'O', 'ms'];
for (var i = 0; i < domPrefixes.length; i++) {
if (isPresent(this.getStyle(element, domPrefixes[i] + 'AnimationName'))) {
this._animationPrefix = '-' + domPrefixes[i].toLowerCase() + '-';
break;
}
}
}
var transEndEventNames: {[key: string]: string} = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'oTransitionEnd otransitionend',
transition: 'transitionend'
};
StringMapWrapper.forEach(transEndEventNames, (value: string, key: string) => {
if (isPresent(this.getStyle(element, key))) {
this._transitionEnd = value;
}
});
} catch (e) {
this._animationPrefix = null;
this._transitionEnd = null;
}
}
getXHR(): Type {
return XHRImpl;
}
getDistributedNodes(el: HTMLElement): Node[] {
return (<any>el).getDistributedNodes();
}
resolveAndSetHref(el: HTMLAnchorElement, baseUrl: string, href: string) {
el.href = href == null ? baseUrl : baseUrl + '/../' + href;
}
supportsDOMEvents(): boolean {
return true;
}
supportsNativeShadowDOM(): boolean {
return isFunction((<any>this.defaultDoc().body).createShadowRoot);
}
getAnimationPrefix(): string {
return isPresent(this._animationPrefix) ? this._animationPrefix : '';
}
getTransitionEnd(): string {
return isPresent(this._transitionEnd) ? this._transitionEnd : '';
}
supportsAnimation(): boolean {
return isPresent(this._animationPrefix) && isPresent(this._transitionEnd);
}
}
-259
View File
@@ -1,259 +0,0 @@
import {isBlank, Type} from 'angular2/src/facade/lang';
export var DOM: DomAdapter = null;
export function setRootDomAdapter(adapter: DomAdapter) {
if (isBlank(DOM)) {
DOM = adapter;
}
}
/* tslint:disable:requireParameterType */
/**
* Provides DOM operations in an environment-agnostic way.
*/
export abstract class DomAdapter {
abstract hasProperty(element: any, name: string): boolean;
abstract setProperty(el: Element, name: string, value: any): void;
abstract getProperty(el: Element, name: string): any;
abstract invoke(el: Element, methodName: string, args: any[]): any;
abstract logError(error: any): void;
abstract log(error: any): void;
abstract logGroup(error: any): void;
abstract logGroupEnd(): void;
/** @deprecated */
abstract getXHR(): Type;
/**
* Maps attribute names to their corresponding property names for cases
* where attribute name doesn't match property name.
*/
get attrToPropMap(): {[key: string]: string} {
return this._attrToPropMap;
};
set attrToPropMap(value: {[key: string]: string}) {
this._attrToPropMap = value;
};
/** @internal */
_attrToPropMap: {[key: string]: string};
abstract parse(templateHtml: string): any;
abstract query(selector: string): any;
abstract querySelector(el: any, selector: string): HTMLElement;
abstract querySelectorAll(el: any, selector: string): any[];
abstract on(el: any, evt: any, listener: any): void;
abstract onAndCancel(el: any, evt: any, listener: any): Function;
abstract dispatchEvent(el: any, evt: any): void;
abstract createMouseEvent(eventType: any): any;
abstract createEvent(eventType: string): any;
abstract preventDefault(evt: any): void;
abstract isPrevented(evt: any): boolean;
abstract getInnerHTML(el: any): string;
abstract getOuterHTML(el: any): string;
abstract nodeName(node: any): string;
abstract nodeValue(node: any): string;
abstract type(node: any): string;
abstract content(node: any): any;
abstract firstChild(el: any): Node;
abstract nextSibling(el: any): Node;
abstract parentElement(el: any): Node;
abstract childNodes(el: any): Node[];
abstract childNodesAsList(el: any): Node[];
abstract clearNodes(el: any): void;
abstract appendChild(el: any, node: any): void;
abstract removeChild(el: any, node: any): void;
abstract replaceChild(el: any, newNode: any, oldNode: any): void;
abstract remove(el: any): Node;
abstract insertBefore(el: any, node: any): void;
abstract insertAllBefore(el: any, nodes: any): void;
abstract insertAfter(el: any, node: any): void;
abstract setInnerHTML(el: any, value: any): void;
abstract getText(el: any): string;
abstract setText(el: any, value: string): void;
abstract getValue(el: any): string;
abstract setValue(el: any, value: string): void;
abstract getChecked(el: any): boolean;
abstract setChecked(el: any, value: boolean): void;
abstract createComment(text: string): any;
abstract createTemplate(html: any): HTMLElement;
abstract createElement(tagName: any, doc?: any): HTMLElement;
abstract createElementNS(ns: string, tagName: string, doc?: any): Element;
abstract createTextNode(text: string, doc?: any): Text;
abstract createScriptTag(attrName: string, attrValue: string, doc?: any): HTMLElement;
abstract createStyleElement(css: string, doc?: any): HTMLStyleElement;
abstract createShadowRoot(el: any): any;
abstract getShadowRoot(el: any): any;
abstract getHost(el: any): any;
abstract getDistributedNodes(el: any): Node[];
abstract clone /*<T extends Node>*/(node: Node /*T*/): Node /*T*/;
abstract getElementsByClassName(element: any, name: string): HTMLElement[];
abstract getElementsByTagName(element: any, name: string): HTMLElement[];
abstract classList(element: any): any[];
abstract addClass(element: any, className: string): void;
abstract removeClass(element: any, className: string): void;
abstract hasClass(element: any, className: string): boolean;
abstract setStyle(element: any, styleName: string, styleValue: string): void;
abstract removeStyle(element: any, styleName: string): void;
abstract getStyle(element: any, styleName: string): string;
abstract hasStyle(element: any, styleName: string, styleValue?: string): boolean;
abstract tagName(element: any): string;
abstract attributeMap(element: any): Map<string, string>;
abstract hasAttribute(element: any, attribute: string): boolean;
abstract hasAttributeNS(element: any, ns: string, attribute: string): boolean;
abstract getAttribute(element: any, attribute: string): string;
abstract getAttributeNS(element: any, ns: string, attribute: string): string;
abstract setAttribute(element: any, name: string, value: string): void;
abstract setAttributeNS(element: any, ns: string, name: string, value: string): void;
abstract removeAttribute(element: any, attribute: string): void;
abstract removeAttributeNS(element: any, ns: string, attribute: string): void;
abstract templateAwareRoot(el: any): any;
abstract createHtmlDocument(): HTMLDocument;
abstract defaultDoc(): HTMLDocument;
abstract getBoundingClientRect(el: any): any;
abstract getTitle(): string;
abstract setTitle(newTitle: string): void;
abstract elementMatches(n: any, selector: string): boolean;
abstract isTemplateElement(el: any): boolean;
abstract isTextNode(node: any): boolean;
abstract isCommentNode(node: any): boolean;
abstract isElementNode(node: any): boolean;
abstract hasShadowRoot(node: any): boolean;
abstract isShadowRoot(node: any): boolean;
abstract importIntoDoc /*<T extends Node>*/(node: Node /*T*/): Node /*T*/;
abstract adoptNode /*<T extends Node>*/(node: Node /*T*/): Node /*T*/;
abstract getHref(element: any): string;
abstract getEventKey(event: any): string;
abstract resolveAndSetHref(element: any, baseUrl: string, href: string): any;
abstract supportsDOMEvents(): boolean;
abstract supportsNativeShadowDOM(): boolean;
abstract getGlobalEventTarget(target: string): any;
abstract getHistory(): History;
abstract getLocation(): Location;
abstract getBaseHref(): string;
abstract resetBaseElement(): void;
abstract getUserAgent(): string;
abstract setData(element: any, name: string, value: string): void;
abstract getComputedStyle(element: any): any;
abstract getData(element: any, name: string): string;
abstract setGlobalVar(name: string, value: any): void;
abstract requestAnimationFrame(callback: any): number;
abstract cancelAnimationFrame(id: any): void;
abstract performanceNow(): number;
abstract getAnimationPrefix(): string;
abstract getTransitionEnd(): string;
abstract supportsAnimation(): boolean;
}
+1 -3
View File
@@ -37,9 +37,7 @@ export class DomPortalHost extends BasePortalHost {
// is a bug in Angular.
portal.locals.forEach((v, k) => viewRef.setLocal(k, v));
viewRef.rootNodes.forEach(rootNode => {
this._hostDomElement.appendChild(rootNode);
});
viewRef.rootNodes.forEach(rootNode => this._hostDomElement.appendChild(rootNode));
this.setDisposeFn((() => {
let index = viewContainer.indexOf(viewRef);
+17 -21
View File
@@ -1,14 +1,12 @@
import {Portal} from './portal';
import {TemplatePortal} from './portal';
import {ComponentRef} from 'angular2/core';
import {ComponentPortal} from './portal';
import {Directive} from 'angular2/core';
import {TemplateRef} from 'angular2/core';
import {BasePortalHost} from './portal';
import {DynamicComponentLoader} from 'angular2/core';
import {ElementRef} from 'angular2/core';
import {ViewContainerRef} from 'angular2/core';
import {
ComponentRef,
Directive,
TemplateRef,
DynamicComponentLoader,
ElementRef,
ViewContainerRef
} from 'angular2/core';
import {Portal, TemplatePortal, ComponentPortal, BasePortalHost} from './portal';
/**
* Directive version of a `TemplatePortal`. Because the directive *is* a TemplatePortal,
@@ -69,12 +67,11 @@ export class PortalHostDirective extends BasePortalHost {
let elementRef = portal.origin != null ? portal.origin : this._elementRef;
// Typecast is necessary for Dart transpilation.
return <Promise<ComponentRef>>
this._dynamicComponentLoader.loadNextToLocation(portal.component, elementRef)
.then(ref => {
this.setDisposeFn(() => ref.dispose());
return ref;
});
return this._dynamicComponentLoader.loadNextToLocation(portal.component, elementRef)
.then(ref => {
this.setDisposeFn(() => ref.dispose());
return ref;
});
}
/** Attach the given TemplatePortal to this PortlHost as an embedded View. */
@@ -86,15 +83,14 @@ export class PortalHostDirective extends BasePortalHost {
this.setDisposeFn(() => this._viewContainerRef.clear());
// TODO(jelbourn): return locals from view
// Typecast is necessary for Dart transpilation.
return <Promise<Map<string, any>>> Promise.resolve(new Map<string, any>());
return Promise.resolve(new Map<string, any>());
}
/** Detatches the currently attached Portal (if there is one) and attaches the given Portal. */
private _replaceAttachedPortal(p: Portal<any>): void {
let maybeDetach = this.hasAttached() ? this.detach() : Promise.resolve(null);
let maybeDetach = this.hasAttached() ? this.detach() : Promise.resolve();
maybeDetach.then(_ => {
maybeDetach.then(() => {
if (p != null) {
this.attach(p);
this._portal = p;
+5 -10
View File
@@ -1,14 +1,12 @@
import {
inject,
ComponentFixture,
TestComponentBuilder,
} from 'angular2/testing';
import {
it,
describe,
expect,
beforeEach,
} from '../../core/facade/testing';
inject,
ComponentFixture,
TestComponentBuilder,
} from 'angular2/testing';
import {Component, ViewChildren, QueryList, ElementRef} from 'angular2/core';
import {TemplatePortalDirective} from './portal-directives';
import {Portal} from './portal';
@@ -19,8 +17,6 @@ import {flushMicrotasks} from 'angular2/testing';
import {DynamicComponentLoader} from 'angular2/core';
import {AppViewManager} from 'angular2/core';
import {DomPortalHost} from './dom-portal-host';
import {BrowserDomAdapter} from '../platform/browser/browser_adapter';
import {DOM} from '../platform/dom/dom_adapter';
@@ -30,7 +26,6 @@ export function main() {
beforeEach(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
builder = tcb;
BrowserDomAdapter.makeCurrent();
}));
describe('PortalHostDirective', () => {
@@ -234,7 +229,7 @@ export function main() {
fakeAsync((dcl: DynamicComponentLoader, avm: AppViewManager) => {
viewManager = avm;
componentLoader = dcl;
someDomElement = DOM.createElement('div');
someDomElement = document.createElement('div');
host = new DomPortalHost(someDomElement, componentLoader, viewManager);
builder.createAsync(ArbitraryElementRefComponent).then(fixture => {
+7 -8
View File
@@ -1,7 +1,6 @@
import {EventEmitter} from 'angular2/src/facade/async';
import {Directive, HostBinding, Output, Input} from 'angular2/core';
import {OneOf} from '../annotations/one-of';
import {Directive, HostBinding, Output, Input, EventEmitter} from 'angular2/core';
export type LayoutDirection = 'ltr' | 'rtl';
/**
* Directive to listen to changes of direction of part of the DOM.
@@ -15,15 +14,15 @@ import {OneOf} from '../annotations/one-of';
exportAs: '$implicit'
})
export class Dir {
@Input('dir') @OneOf(['ltr', 'rtl']) private _dir: string = 'ltr';
@Input('dir') private _dir: LayoutDirection = 'ltr';
@Output() dirChange = new EventEmitter<void>();
@HostBinding('attr.dir')
get dir(): string {
get dir(): LayoutDirection {
return this._dir;
}
set dir(v: string) {
set dir(v: LayoutDirection) {
let old = this._dir;
this._dir = v;
if (old != this._dir) {
@@ -31,6 +30,6 @@ export class Dir {
}
}
get value(): string { return this.dir; }
set value(v: string) { this.dir = v; }
get value(): LayoutDirection { return this.dir; }
set value(v: LayoutDirection) { this.dir = v; }
}
-3
View File
@@ -1,14 +1,11 @@
import {bootstrap} from 'angular2/platform/browser';
import {DemoApp} from './demo-app/demo-app';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {BrowserDomAdapter} from './core/platform/browser/browser_adapter';
import {OVERLAY_CONTAINER_TOKEN} from './core/overlay/overlay';
import {MdLiveAnnouncer} from './core/live-announcer/live-announcer';
import {provide} from 'angular2/core';
import {createOverlayContainer} from './core/overlay/overlay-container';
BrowserDomAdapter.makeCurrent();
bootstrap(DemoApp, [
ROUTER_PROVIDERS,
MdLiveAnnouncer,