feat(compiler): DOM adapters + html5lib implementation; misc fixes

This commit is contained in:
Yegor Jbanov
2015-02-27 14:50:06 -08:00
parent ab42664e76
commit 757eae8ad3
79 changed files with 1223 additions and 643 deletions

View File

@ -1,6 +1,7 @@
import {Injector, bind, OpaqueToken} from 'angular2/di';
import {Type, FIELD, isBlank, isPresent, BaseException, assertionsEnabled, print} from 'angular2/src/facade/lang';
import {DOM, Element} from 'angular2/src/facade/dom';
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Compiler, CompilerCache} from './compiler/compiler';
import {ProtoView} from './compiler/view';
import {Reflector, reflector} from 'angular2/src/reflection/reflection';
@ -117,6 +118,7 @@ function _createVmZone(givenReporter:Function): VmTurnZone {
// Multiple calls to this method are allowed. Each application would only share
// _rootInjector, which is not user-configurable by design, thus safe to share.
export function bootstrap(appComponentType: Type, bindings: List<Binding>=null, givenBootstrapErrorReporter: Function=null): Promise {
BrowserDomAdapter.makeCurrent();
var bootstrapProcess = PromiseWrapper.completer();
var zone = _createVmZone(givenBootstrapErrorReporter);

View File

@ -1,7 +1,6 @@
import {Type, isBlank, isPresent, BaseException, normalizeBlank, stringify} from 'angular2/src/facade/lang';
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
import {List, ListWrapper, Map, MapWrapper} from 'angular2/src/facade/collection';
import {DOM, Element} from 'angular2/src/facade/dom';
import {ChangeDetection, Parser} from 'angular2/change_detection';
@ -149,7 +148,7 @@ export class Compiler {
}
// TODO(vicb): union type return ProtoView or Promise<ProtoView>
_compileTemplate(template: Template, tplElement: Element, component: Type) {
_compileTemplate(template: Template, tplElement, component: Type) {
var pipeline = new CompilePipeline(this.createSteps(component, template));
var compilationCtxtDescription = stringify(this._reader.read(component).type);
var compileElements;

View File

@ -1,5 +1,5 @@
import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
import {Element, DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {int, isBlank, isPresent, Type, StringJoiner, assertionsEnabled} from 'angular2/src/facade/lang';
import {DirectiveMetadata} from '../directive_metadata';
import {Decorator, Component, Viewport} from '../../annotations/annotations';
@ -15,7 +15,7 @@ import {AST} from 'angular2/change_detection';
* by the CompileSteps starting out with the pure HTMLElement.
*/
export class CompileElement {
element:Element;
element;
_attrs:Map;
_classList:List;
textNodeBindings:Map;
@ -40,7 +40,7 @@ export class CompileElement {
ignoreBindings: boolean;
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of error
constructor(element:Element, compilationUnit = '') {
constructor(element, compilationUnit = '') {
this.element = element;
this._attrs = null;
this._classList = null;
@ -177,7 +177,7 @@ export class CompileElement {
// return an HTML representation of an element start tag - without its content
// this is used to give contextual information in case of errors
function getElementDescription(domElement:Element):string {
function getElementDescription(domElement):string {
var buf = new StringJoiner();
var atts = DOM.attributeMap(domElement);

View File

@ -1,6 +1,6 @@
import {isPresent} from 'angular2/src/facade/lang';
import {List, ListWrapper} from 'angular2/src/facade/collection';
import {Element, DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {CompileElement} from './compile_element';
import {CompileControl} from './compile_control';
import {CompileStep} from './compile_step';
@ -15,7 +15,7 @@ export class CompilePipeline {
this._control = new CompileControl(steps);
}
process(rootElement:Element, compilationCtxtDescription:string = ''):List {
process(rootElement, compilationCtxtDescription:string = ''):List {
var results = ListWrapper.create();
this._process(results, null, new CompileElement(rootElement, compilationCtxtDescription), compilationCtxtDescription);
return results;

View File

@ -1,6 +1,6 @@
import {isPresent, isBlank, BaseException, assertionsEnabled, RegExpWrapper} from 'angular2/src/facade/lang';
import {List, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {SelectorMatcher} from '../selector';
import {CssSelector} from '../selector';

View File

@ -1,5 +1,5 @@
import {int, isPresent, isBlank, Type, BaseException, StringWrapper, RegExpWrapper, isString, stringify} from 'angular2/src/facade/lang';
import {Element, DOM, attrToPropMap} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {ListWrapper, List, MapWrapper, StringMapWrapper} from 'angular2/src/facade/collection';
import {reflector} from 'angular2/src/reflection/reflection';
@ -21,7 +21,7 @@ function ariaSetterFactory(attrName:string) {
var setterFn = StringMapWrapper.get(ariaSettersCache, attrName);
if (isBlank(setterFn)) {
setterFn = function(element:Element, value) {
setterFn = function(element, value) {
if (isPresent(value)) {
DOM.setAttribute(element, attrName, stringify(value));
} else {
@ -42,7 +42,7 @@ function classSetterFactory(className:string) {
var setterFn = StringMapWrapper.get(classSettersCache, className);
if (isBlank(setterFn)) {
setterFn = function(element:Element, value) {
setterFn = function(element, value) {
if (value) {
DOM.addClass(element, className);
} else {
@ -64,7 +64,7 @@ function styleSetterFactory(styleName:string, stylesuffix:string) {
var setterFn = StringMapWrapper.get(styleSettersCache, cacheKey);
if (isBlank(setterFn)) {
setterFn = function(element:Element, value) {
setterFn = function(element, value) {
var valAsStr;
if (isPresent(value)) {
valAsStr = stringify(value);
@ -80,7 +80,7 @@ function styleSetterFactory(styleName:string, stylesuffix:string) {
}
const ROLE_ATTR = 'role';
function roleSetter(element:Element, value) {
function roleSetter(element, value) {
if (isString(value)) {
DOM.setAttribute(element, ROLE_ATTR, value);
} else {
@ -92,18 +92,25 @@ function roleSetter(element:Element, value) {
}
// special mapping for cases where attribute name doesn't match property name
var attrToProp = StringMapWrapper.merge({
"inner-html": "innerHTML",
"readonly": "readOnly",
"tabindex": "tabIndex",
}, attrToPropMap);
var _lazyAttrToProp;
function attrToProp() {
if (!isPresent(_lazyAttrToProp)) {
_lazyAttrToProp = StringMapWrapper.merge({
"inner-html": "innerHTML",
"readonly": "readOnly",
"tabindex": "tabIndex",
}, DOM.attrToPropMap);
}
return _lazyAttrToProp;
}
// tells if an attribute is handled by the ElementBinderBuilder step
export function isSpecialProperty(propName:string) {
return StringWrapper.startsWith(propName, ARIA_PREFIX)
|| StringWrapper.startsWith(propName, CLASS_PREFIX)
|| StringWrapper.startsWith(propName, STYLE_PREFIX)
|| StringMapWrapper.contains(attrToProp, propName);
|| StringMapWrapper.contains(attrToProp(), propName);
}
/**
@ -250,7 +257,7 @@ export class ElementBinderBuilder extends CompileStep {
}
_resolvePropertyName(attrName:string) {
var mappedPropName = StringMapWrapper.get(attrToProp, attrName);
var mappedPropName = StringMapWrapper.get(attrToProp(), attrName);
return isPresent(mappedPropName) ? mappedPropName : attrName;
}
}

View File

@ -1,6 +1,6 @@
import {isPresent} from 'angular2/src/facade/lang';
import {MapWrapper} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {CompileStep} from './compile_step';
import {CompileElement} from './compile_element';

View File

@ -5,7 +5,7 @@ import {CompileControl} from './compile_control';
import {DirectiveMetadata} from 'angular2/src/core/compiler/directive_metadata';
import {ShadowDomStrategy} from 'angular2/src/core/compiler/shadow_dom_strategy';
import {DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Type} from 'angular2/src/facade/lang';
import {PromiseWrapper} from 'angular2/src/facade/async';
import {ListWrapper} from 'angular2/src/facade/collection';

View File

@ -1,5 +1,5 @@
import {RegExpWrapper, StringWrapper, isPresent} from 'angular2/src/facade/lang';
import {DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Parser} from 'angular2/change_detection';

View File

@ -1,5 +1,5 @@
import {isBlank, isPresent, BaseException} from 'angular2/src/facade/lang';
import {DOM, TemplateElement} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {Parser} from 'angular2/change_detection';
@ -64,8 +64,8 @@ export class ViewSplitter extends CompileStep {
if (DOM.isTemplateElement(current.element)) {
if (!current.isViewRoot) {
var viewRoot = new CompileElement(DOM.createTemplate(''));
var currentElement:TemplateElement = current.element;
var viewRootElement:TemplateElement = viewRoot.element;
var currentElement = current.element;
var viewRootElement = viewRoot.element;
this._moveChildNodes(DOM.content(currentElement), DOM.content(viewRootElement));
// viewRoot doesn't appear in the original template, so we associate
// the current element description to get a more meaningful message in case of error

View File

@ -1,16 +1,14 @@
import {Decorator} from '../../annotations/annotations';
import {SourceLightDom, DestinationLightDom, LightDom} from './light_dom';
import {Inject} from 'angular2/di';
import {Element, Node, DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {isPresent} from 'angular2/src/facade/lang';
import {List, ListWrapper} from 'angular2/src/facade/collection';
import {NgElement} from 'angular2/src/core/dom/element';
var _scriptTemplate = DOM.createScriptTag('type', 'ng/content')
class ContentStrategy {
nodes: List<Node>;
insert(nodes:List<Node>){}
nodes:List;
insert(nodes:List){}
}
/**
@ -19,34 +17,42 @@ class ContentStrategy {
* and thus does not affect redistribution.
*/
class RenderedContent extends ContentStrategy {
beginScript:Element;
endScript:Element;
static _lazyScriptTemplate;
beginScript;
endScript;
constructor(contentEl:Element) {
constructor(contentEl) {
super();
this._replaceContentElementWithScriptTags(contentEl);
this.nodes = [];
}
_scriptTemplate() {
if (!isPresent(RenderedContent._lazyScriptTemplate)) {
RenderedContent._lazyScriptTemplate = DOM.createScriptTag('type', 'ng/content');
}
return RenderedContent._lazyScriptTemplate;
}
// Inserts the nodes in between the start and end scripts.
// Previous content is removed.
insert(nodes:List<Node>) {
insert(nodes:List) {
this.nodes = nodes;
DOM.insertAllBefore(this.endScript, nodes);
this._removeNodesUntil(ListWrapper.isEmpty(nodes) ? this.endScript : nodes[0]);
}
// Replaces the content tag with a pair of script tags
_replaceContentElementWithScriptTags(contentEl:Element) {
this.beginScript = DOM.clone(_scriptTemplate);
this.endScript = DOM.clone(_scriptTemplate);
_replaceContentElementWithScriptTags(contentEl) {
this.beginScript = DOM.clone(this._scriptTemplate());
this.endScript = DOM.clone(this._scriptTemplate());
DOM.insertBefore(contentEl, this.beginScript);
DOM.insertBefore(contentEl, this.endScript);
DOM.removeChild(DOM.parentElement(contentEl), contentEl);
}
_removeNodesUntil(node:Node) {
_removeNodesUntil(node) {
var p = DOM.parentElement(this.beginScript);
for (var next = DOM.nextSibling(this.beginScript);
next !== node;
@ -70,7 +76,7 @@ class IntermediateContent extends ContentStrategy {
this.nodes = [];
}
insert(nodes:List<Node>) {
insert(nodes:List) {
this.nodes = nodes;
this.destinationLightDom.redistribute();
}
@ -91,11 +97,11 @@ export class Content {
new RenderedContent(contentEl.domElement);
}
nodes():List<Node> {
nodes():List {
return this._strategy.nodes;
}
insert(nodes:List<Node>) {
insert(nodes:List) {
this._strategy.insert(nodes);
}
}

View File

@ -1,4 +1,4 @@
import {Element, Node, DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {List, ListWrapper} from 'angular2/src/facade/collection';
import {isBlank, isPresent} from 'angular2/src/facade/lang';
@ -12,7 +12,7 @@ export class DestinationLightDom {}
class _Root {
node:Node;
node;
injector:ElementInjector;
constructor(node, injector) {
@ -29,10 +29,10 @@ export class LightDom {
// The shadow DOM
shadowDomView:View;
// The nodes of the light DOM
nodes:List<Node>;
nodes:List;
roots:List<_Root>;
constructor(lightDomView:View, shadowDomView:View, element:Element) {
constructor(lightDomView:View, shadowDomView:View, element) {
this.lightDomView = lightDomView;
this.shadowDomView = shadowDomView;
this.nodes = DOM.childNodesAsList(element);
@ -113,7 +113,7 @@ export class LightDom {
}
// Projects the light DOM into the shadow DOM
function redistributeNodes(contents:List<Content>, nodes:List<Node>) {
function redistributeNodes(contents:List<Content>, nodes:List) {
for (var i = 0; i < contents.length; ++i) {
var content = contents[i];
var select = content.select;

View File

@ -1,10 +1,4 @@
import {
StyleElement,
DOM,
CssRule,
CssKeyframesRule,
CSSRuleWrapper
} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {List, ListWrapper} from 'angular2/src/facade/collection';
import {
StringWrapper,
@ -153,7 +147,7 @@ export class ShadowCss {
* Shim a style element with the given selector. Returns cssText that can
* be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
*/
shimStyle(style: StyleElement, selector: string, hostSelector: string = ''): string {
shimStyle(style, selector: string, hostSelector: string = ''): string {
var cssText = DOM.getText(style);
return this.shimCssText(cssText, selector, hostSelector);
}
@ -353,11 +347,11 @@ export class ShadowCss {
if (isPresent(cssRules)) {
for (var i = 0; i < cssRules.length; i++) {
var rule = cssRules[i];
if (CSSRuleWrapper.isStyleRule(rule) || CSSRuleWrapper.isPageRule(rule)) {
if (DOM.isStyleRule(rule) || DOM.isPageRule(rule)) {
cssText += this._scopeSelector(rule.selectorText, scopeSelector, hostSelector,
this.strictStyling) + ' {\n';
cssText += this._propertiesFromRule(rule) + '\n}\n\n';
} else if (CSSRuleWrapper.isMediaRule(rule)) {
} else if (DOM.isMediaRule(rule)) {
cssText += '@media ' + rule.media.mediaText + ' {\n';
cssText += this._scopeRules(rule.cssRules, scopeSelector, hostSelector);
cssText += '\n}\n\n';
@ -372,7 +366,7 @@ export class ShadowCss {
cssText += rule.cssText + '\n\n';
}
} catch(x) {
if (CSSRuleWrapper.isKeyframesRule(rule) && isPresent(rule.cssRules)) {
if (DOM.isKeyframesRule(rule) && isPresent(rule.cssRules)) {
cssText += this._ieSafeCssTextFromKeyFrameRule(rule);
}
}
@ -382,7 +376,7 @@ export class ShadowCss {
return cssText;
}
_ieSafeCssTextFromKeyFrameRule(rule: CssKeyframesRule): string {
_ieSafeCssTextFromKeyFrameRule(rule): string {
var cssText = '@keyframes ' + rule.name + ' {';
for (var i = 0; i < rule.cssRules.length; i++) {
var r = rule.cssRules[i];

View File

@ -1,5 +1,5 @@
import {Type, isBlank, isPresent, int} from 'angular2/src/facade/lang';
import {DOM, Element, StyleElement} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {List, ListWrapper, MapWrapper, Map} from 'angular2/src/facade/collection';
import {PromiseWrapper} from 'angular2/src/facade/async';
@ -13,14 +13,14 @@ import {StyleInliner} from './style_inliner';
import {StyleUrlResolver} from './style_url_resolver';
export class ShadowDomStrategy {
attachTemplate(el:Element, view:View) {}
constructLightDom(lightDomView:View, shadowDomView:View, el:Element) {}
attachTemplate(el, view:View) {}
constructLightDom(lightDomView:View, shadowDomView:View, el) {}
polyfillDirectives():List<Type> { return null; }
// TODO(vicb): union types: return either a string or a Promise<string>
transformStyleText(cssText: string, baseUrl: string, component: Type) {}
handleStyleElement(styleEl: StyleElement) {};
shimContentElement(component: Type, element: Element) {}
shimHostElement(component: Type, element: Element) {}
handleStyleElement(styleEl) {};
shimContentElement(component: Type, element) {}
shimHostElement(component: Type, element) {}
}
/**
@ -34,21 +34,21 @@ export class ShadowDomStrategy {
*/
export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
_styleUrlResolver: StyleUrlResolver;
_lastInsertedStyle: StyleElement;
_styleHost: Element;
_lastInsertedStyle;
_styleHost;
constructor(styleUrlResolver: StyleUrlResolver, styleHost: Element) {
constructor(styleUrlResolver: StyleUrlResolver, styleHost) {
super();
this._styleUrlResolver = styleUrlResolver;
this._styleHost = styleHost;
}
attachTemplate(el:Element, view:View){
attachTemplate(el, view:View){
DOM.clearNodes(el);
_moveViewNodesIntoParent(el, view);
}
constructLightDom(lightDomView:View, shadowDomView:View, el:Element){
constructLightDom(lightDomView:View, shadowDomView:View, el) {
return new LightDom(lightDomView, shadowDomView, el);
}
@ -60,7 +60,7 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
return this._styleUrlResolver.resolveUrls(cssText, baseUrl);
}
handleStyleElement(styleEl: StyleElement) {
handleStyleElement(styleEl) {
DOM.remove(styleEl);
var cssText = DOM.getText(styleEl);
@ -73,7 +73,7 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
}
};
_insertStyleElement(host: Element, style: StyleElement) {
_insertStyleElement(host, style) {
if (isBlank(this._lastInsertedStyle)) {
var firstChild = DOM.firstChild(host);
if (isPresent(firstChild)) {
@ -103,7 +103,7 @@ export class EmulatedUnscopedShadowDomStrategy extends ShadowDomStrategy {
export class EmulatedScopedShadowDomStrategy extends EmulatedUnscopedShadowDomStrategy {
_styleInliner: StyleInliner;
constructor(styleInliner: StyleInliner, styleUrlResolver: StyleUrlResolver, styleHost: Element) {
constructor(styleInliner: StyleInliner, styleUrlResolver: StyleUrlResolver, styleHost) {
super(styleUrlResolver, styleHost);
this._styleInliner = styleInliner;
}
@ -118,18 +118,18 @@ export class EmulatedScopedShadowDomStrategy extends EmulatedUnscopedShadowDomSt
}
}
handleStyleElement(styleEl: StyleElement) {
handleStyleElement(styleEl) {
DOM.remove(styleEl);
this._insertStyleElement(this._styleHost, styleEl);
};
shimContentElement(component: Type, element: Element) {
shimContentElement(component: Type, element) {
var id = _getComponentId(component);
var attrName = _getContentAttribute(id);
DOM.setAttribute(element, attrName, '');
}
shimHostElement(component: Type, element: Element) {
shimHostElement(component: Type, element) {
var id = _getComponentId(component);
var attrName = _getHostAttribute(id);
DOM.setAttribute(element, attrName, '');
@ -150,11 +150,11 @@ export class NativeShadowDomStrategy extends ShadowDomStrategy {
this._styleUrlResolver = styleUrlResolver;
}
attachTemplate(el:Element, view:View){
attachTemplate(el, view:View){
_moveViewNodesIntoParent(DOM.createShadowRoot(el), view);
}
constructLightDom(lightDomView:View, shadowDomView:View, el:Element){
constructLightDom(lightDomView:View, shadowDomView:View, el) {
return null;
}

View File

@ -1,6 +1,6 @@
import {isBlank, isPresent, BaseException, stringify} from 'angular2/src/facade/lang';
import {DOM, Element} from 'angular2/src/facade/dom';
import {Map, MapWrapper, StringMapWrapper, StringMap} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {XHR} from './xhr/xhr';

View File

@ -1,8 +1,8 @@
import {isPresent, isBlank, RegExpWrapper, BaseException} from 'angular2/src/facade/lang';
import {DOM, AnchorElement} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
export class UrlResolver {
static a: AnchorElement;
static a;
constructor() {
if (isBlank(UrlResolver.a)) {

View File

@ -1,4 +1,4 @@
import {DOM, Element, Node, Text, DocumentFragment} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {Promise} from 'angular2/src/facade/async';
import {ListWrapper, MapWrapper, StringMapWrapper, List} from 'angular2/src/facade/collection';
import {AST, ContextWithVariableBindings, ChangeDispatcher, ProtoChangeDetector, ChangeDetector, ChangeRecord}
@ -33,12 +33,12 @@ export class View {
/// This list matches the _nodes list. It is sparse, since only Elements have ElementInjector
rootElementInjectors:List<ElementInjector>;
elementInjectors:List<ElementInjector>;
bindElements:List<Element>;
textNodes:List<Text>;
bindElements:List;
textNodes:List;
changeDetector:ChangeDetector;
/// When the view is part of render tree, the DocumentFragment is empty, which is why we need
/// to keep track of the nodes.
nodes:List<Node>;
nodes:List;
componentChildViews: List<View>;
viewContainers: List<ViewContainer>;
preBuiltObjects: List<PreBuiltObjects>;
@ -46,7 +46,7 @@ export class View {
context: any;
contextWithLocals:ContextWithVariableBindings;
constructor(proto:ProtoView, nodes:List<Node>, protoChangeDetector:ProtoChangeDetector, protoContextLocals:Map) {
constructor(proto:ProtoView, nodes:List, protoChangeDetector:ProtoChangeDetector, protoContextLocals:Map) {
this.proto = proto;
this.nodes = nodes;
this.changeDetector = protoChangeDetector.instantiate(this);
@ -262,7 +262,7 @@ export class View {
}
export class ProtoView {
element:Element;
element;
elementBinders:List<ElementBinder>;
protoChangeDetector:ProtoChangeDetector;
variableBindings: Map;
@ -277,7 +277,7 @@ export class ProtoView {
stylePromises: List<Promise>;
constructor(
template:Element,
template,
protoChangeDetector:ProtoChangeDetector,
shadowDomStrategy: ShadowDomStrategy) {
this.element = template;
@ -558,8 +558,8 @@ export class ElementBindingMemento {
this._setter = setter;
}
invoke(record:ChangeRecord, bindElements:List<Element>) {
var element:Element = bindElements[this._elementIndex];
invoke(record:ChangeRecord, bindElements:List) {
var element = bindElements[this._elementIndex];
this._setter(element, record.currentValue);
}
}

View File

@ -1,5 +1,5 @@
import * as viewModule from './view';
import {DOM, Node, Element} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {ListWrapper, MapWrapper, List} from 'angular2/src/facade/collection';
import {BaseException} from 'angular2/src/facade/lang';
import {Injector} from 'angular2/di';
@ -9,7 +9,7 @@ import {EventManager} from 'angular2/src/core/events/event_manager';
export class ViewContainer {
parentView: viewModule.View;
templateElement: Element;
templateElement;
defaultProtoView: viewModule.ProtoView;
_views: List<viewModule.View>;
_lightDom: any;
@ -18,7 +18,7 @@ export class ViewContainer {
appInjector: Injector;
hostElementInjector: eiModule.ElementInjector;
constructor(parentView: viewModule.View, templateElement: Element, defaultProtoView: viewModule.ProtoView,
constructor(parentView: viewModule.View, templateElement, defaultProtoView: viewModule.ProtoView,
elementInjector: eiModule.ElementInjector, eventManager: EventManager, lightDom = null) {
this.parentView = parentView;
this.templateElement = templateElement;
@ -124,7 +124,7 @@ export class ViewContainer {
return this._views;
}
nodes():List<Node> {
nodes():List {
var r = [];
for (var i = 0; i < this._views.length; ++i) {
r = ListWrapper.concat(r, this._views[i].nodes);

View File

@ -1,9 +1,9 @@
import {DOM, Element} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {normalizeBlank} from 'angular2/src/facade/lang';
export class NgElement {
domElement:Element;
constructor(domElement:Element) {
domElement;
constructor(domElement) {
this.domElement = domElement;
}

View File

@ -1,5 +1,5 @@
import {isBlank, BaseException, isPresent, StringWrapper} from 'angular2/src/facade/lang';
import {DOM, Element} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
import {VmTurnZone} from 'angular2/src/core/zone/vm_turn_zone';
@ -17,7 +17,7 @@ export class EventManager {
}
}
addEventListener(element: Element, eventName: string, handler: Function) {
addEventListener(element, eventName: string, handler: Function) {
var shouldSupportBubble = eventName[0] == BUBBLE_SYMBOL;
if (shouldSupportBubble) {
eventName = StringWrapper.substring(eventName, 1);
@ -54,7 +54,7 @@ export class EventManagerPlugin {
return false;
}
addEventListener(element: Element, eventName: string, handler: Function,
addEventListener(element, eventName: string, handler: Function,
shouldSupportBubble: boolean) {
throw "not implemented";
}
@ -69,7 +69,7 @@ export class DomEventsPlugin extends EventManagerPlugin {
return true;
}
addEventListener(element: Element, eventName: string, handler: Function,
addEventListener(element, eventName: string, handler: Function,
shouldSupportBubble: boolean) {
var outsideHandler = shouldSupportBubble ?
DomEventsPlugin.bubbleCallback(element, handler, this.manager._zone) :

View File

@ -2,7 +2,6 @@ library angular.events;
import 'dart:html';
import './hammer_common.dart';
import '../../facade/dom.dart' show Element;
import '../../facade/lang.dart' show BaseException;
import 'dart:js' as js;

View File

@ -1,5 +1,4 @@
import {HammerGesturesPluginCommon} from './hammer_common';
import {Element} from 'angular2/src/facade/dom';
import {isPresent, BaseException} from 'angular2/src/facade/lang';
export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
@ -17,7 +16,7 @@ export class HammerGesturesPlugin extends HammerGesturesPluginCommon {
return true;
}
addEventListener(element: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.');
var zone = this.manager.getZone();
eventName = eventName.toLowerCase();

View File

@ -0,0 +1,194 @@
library angular.core.facade.dom;
import 'dart:html';
import 'dart:js' show JsObject;
import 'dom_adapter.dart' show setRootDomAdapter, DomAdapter;
import '../facade/browser.dart';
// WARNING: Do not expose outside this class. Parsing HTML using this
// sanitizer is a security risk.
class _IdentitySanitizer implements NodeTreeSanitizer {
void sanitizeTree(Node node) {}
}
final _identitySanitizer = new _IdentitySanitizer();
class BrowserDomAdapter extends DomAdapter {
static void makeCurrent() {
setRootDomAdapter(new BrowserDomAdapter());
}
// override JS logic of attribute to property mapping
@override
final attrToPropMap = const {
"inner-html": "innerHtml"
};
query(String selector) => document.querySelector(selector);
Element querySelector(el, String selector) =>
el.querySelector(selector);
ElementList querySelectorAll(el, String selector) =>
el.querySelectorAll(selector);
void on(EventTarget element, String event, callback(arg)) {
// due to https://code.google.com/p/dart/issues/detail?id=17406
// addEventListener misses zones so we use element.on.
element.on[event].listen(callback);
}
void dispatchEvent(EventTarget el, Event evt) {
el.dispatchEvent(evt);
}
MouseEvent createMouseEvent(String eventType) =>
new MouseEvent(eventType, canBubble: true);
createEvent(eventType) =>
new Event(eventType, canBubble: true);
String getInnerHTML(Element el) => el.innerHtml;
String getOuterHTML(Element el) => el.outerHtml;
void setInnerHTML(Element el, String value) {
el.innerHtml = value;
}
String nodeName(Node el) => el.nodeName;
String nodeValue(Node el) => el.nodeValue;
String type(InputElement el) => el.type;
Node content(TemplateElement el) => el.content;
Node firstChild(el) => el.firstChild;
Node nextSibling(Node el) => el.nextNode;
Element parentElement(Node el) => el.parent;
List<Node> childNodes(Node el) => el.childNodes;
List childNodesAsList(Node el) => childNodes(el).toList();
void clearNodes(Node el) {
el.nodes = const [];
}
void appendChild(Node el, Node node) {
el.append(node);
}
void removeChild(Element el, Node node) {
node.remove();
}
Element remove(Element el) {
return el..remove();
}
insertBefore(Node el, node) {
el.parentNode.insertBefore(node, el);
}
void insertAllBefore(Node el, Iterable<Node> nodes) {
el.parentNode.insertAllBefore(nodes, el);
}
void insertAfter(Node el, Node node) {
el.parentNode.insertBefore(node, el.nextNode);
}
String getText(Node el) => el.text;
void setText(Node el, String value) {
el.text = value;
}
String getValue(InputElement el) => el.value;
void setValue(InputElement el, String value) {
el.value = value;
}
bool getChecked(InputElement el) => el.checked;
void setChecked(InputElement el, bool isChecked) {
el.checked = isChecked;
}
TemplateElement createTemplate(String html) {
var t = new TemplateElement();
// We do not sanitize because templates are part of the application code
// not user code.
t.setInnerHtml(html, treeSanitizer: _identitySanitizer);
return t;
}
Element createElement(String tagName, [HtmlDocument doc = null]) {
if (doc == null) doc = document;
return doc.createElement(tagName);
}
createTextNode(String text, [HtmlDocument doc = null]) {
return new Text(text);
}
createScriptTag(String attrName, String attrValue,
[HtmlDocument doc = null]) {
if (doc == null) doc = document;
var el = doc.createElement("SCRIPT");
el.setAttribute(attrName, attrValue);
return el;
}
StyleElement createStyleElement(String css, [HtmlDocument doc = null]) {
if (doc == null) doc = document;
var el = doc.createElement("STYLE");
el.text = css;
return el;
}
ShadowRoot createShadowRoot(Element el) => el.createShadowRoot();
ShadowRoot getShadowRoot(Element el) => el.shadowRoot;
clone(Node node) => node.clone(true);
bool hasProperty(Element element, String name) =>
new JsObject.fromBrowserObject(element).hasProperty(name);
List<Node> getElementsByClassName(Element element, String name) =>
element.getElementsByClassName(name);
List<Node> getElementsByTagName(Element element, String name) =>
element.querySelectorAll(name);
List<String> classList(Element element) => element.classes.toList();
void addClass(Element element, String classname) {
element.classes.add(classname);
}
void removeClass(Element element, String classname) {
element.classes.remove(classname);
}
bool hasClass(Element element, String classname) =>
element.classes.contains(classname);
setStyle(Element element, String stylename, String stylevalue) {
element.style.setProperty(stylename, stylevalue);
}
removeStyle(Element element, String stylename) {
element.style.removeProperty(stylename);
}
getStyle(Element element, String stylename) {
return element.style.getPropertyValue(stylename);
}
String tagName(Element element) => element.tagName;
Map<String, String> attributeMap(Element element) =>
element.attributes;
String getAttribute(Element element, String attribute) =>
element.getAttribute(attribute);
void setAttribute(Element element, String name, String value) {
element.setAttribute(name, value);
}
void removeAttribute(Element element, String name) {
//there is no removeAttribute method as of now in Dart:
//https://code.google.com/p/dart/issues/detail?id=19934
element.attributes.remove(name);
}
Node templateAwareRoot(Element el) =>
el is TemplateElement ? el.content : el;
HtmlDocument createHtmlDocument() =>
document.implementation.createHtmlDocument('fakeTitle');
HtmlDocument defaultDoc() => document;
bool elementMatches(n, String selector) =>
n is Element && n.matches(selector);
bool isTemplateElement(Element el) =>
el is TemplateElement;
bool isTextNode(Node node) =>
node.nodeType == Node.TEXT_NODE;
bool isCommentNode(Node node) => node.nodeType == Node.COMMENT_NODE;
bool isElementNode(Node node) =>
node.nodeType == Node.ELEMENT_NODE;
bool hasShadowRoot(Node node) {
return node is Element && node.shadowRoot != null;
}
Node importIntoDoc(Node node) {
return document.importNode(node, true);
}
isPageRule(CssRule rule) => rule is CssPageRule;
isStyleRule(CssRule rule) => rule is CssStyleRule;
isMediaRule(CssRule rule) => rule is CssMediaRule;
isKeyframesRule(CssRule rule) => rule is CssKeyframesRule;
}

View File

@ -0,0 +1,247 @@
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {isPresent} from 'angular2/src/facade/lang';
import {DomAdapter, setRootDomAdapter} from './dom_adapter';
var EMPTY_MAP = MapWrapper.create();
export class BrowserDomAdapter extends DomAdapter {
static makeCurrent() {
setRootDomAdapter(new BrowserDomAdapter());
}
get attrToPropMap():Map {
return EMPTY_MAP
}
query(selector) {
return document.querySelector(selector);
}
querySelector(el, selector:string):Node {
return el.querySelector(selector);
}
querySelectorAll(el, selector:string):NodeList {
return el.querySelectorAll(selector);
}
on(el, evt, listener) {
el.addEventListener(evt, listener, false);
}
dispatchEvent(el, evt) {
el.dispatchEvent(evt);
}
createMouseEvent(eventType) {
var evt = new MouseEvent(eventType);
evt.initEvent(eventType, true, true);
return evt;
}
createEvent(eventType) {
return new Event(eventType, true);
}
getInnerHTML(el) {
return el.innerHTML;
}
getOuterHTML(el) {
return el.outerHTML;
}
nodeName(node:Node):string {
return node.nodeName;
}
nodeValue(node:Node):string {
return node.nodeValue;
}
type(node:string) {
return node.type;
}
content(node:HTMLTemplateElement):Node {
return node.content;
}
firstChild(el):Node {
return el.firstChild;
}
nextSibling(el):Node {
return el.nextSibling;
}
parentElement(el) {
return el.parentElement;
}
childNodes(el):NodeList {
return el.childNodes;
}
childNodesAsList(el):List {
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) {
el.innerHTML = "";
}
appendChild(el, node) {
el.appendChild(node);
}
removeChild(el, node) {
el.removeChild(node);
}
remove(el) {
var parent = el.parentNode;
parent.removeChild(el);
return el;
}
insertBefore(el, node) {
el.parentNode.insertBefore(node, el);
}
insertAllBefore(el, nodes) {
ListWrapper.forEach(nodes, (n) => {
el.parentNode.insertBefore(n, el);
});
}
insertAfter(el, node) {
el.parentNode.insertBefore(node, el.nextSibling);
}
setInnerHTML(el, value) {
el.innerHTML = value;
}
getText(el) {
return el.textContent;
}
// TODO(vicb): removed Element type because it does not support StyleElement
setText(el, value:string) {
el.textContent = value;
}
getValue(el) {
return el.value;
}
setValue(el, value:string) {
el.value = value;
}
getChecked(el) {
return el.checked;
}
setChecked(el, value:boolean) {
el.checked = value;
}
createTemplate(html) {
var t = document.createElement('template');
t.innerHTML = html;
return t;
}
createElement(tagName, doc=document) {
return doc.createElement(tagName);
}
createTextNode(text: string, doc=document) {
return doc.createTextNode(text);
}
createScriptTag(attrName:string, attrValue:string, doc=document) {
var el = doc.createElement("SCRIPT");
el.setAttribute(attrName, attrValue);
return el;
}
createStyleElement(css:string, doc=document):HTMLStyleElement {
var style = doc.createElement('STYLE');
style.innerText = css;
return style;
}
createShadowRoot(el:HTMLElement): ShadowRoot {
return el.createShadowRoot();
}
getShadowRoot(el:HTMLElement): ShadowRoot {
return el.shadowRoot;
}
clone(node:Node) {
return node.cloneNode(true);
}
hasProperty(element, name:string) {
return name in element;
}
getElementsByClassName(element, name:string) {
return element.getElementsByClassName(name);
}
getElementsByTagName(element, name:string) {
return element.getElementsByTagName(name);
}
classList(element):List {
return Array.prototype.slice.call(element.classList, 0);
}
addClass(element, classname:string) {
element.classList.add(classname);
}
removeClass(element, classname:string) {
element.classList.remove(classname);
}
hasClass(element, classname:string) {
return element.classList.contains(classname);
}
setStyle(element, stylename:string, stylevalue:string) {
element.style[stylename] = stylevalue;
}
removeStyle(element, stylename:string) {
element.style[stylename] = null;
}
getStyle(element, stylename:string) {
return element.style[stylename];
}
tagName(element):string {
return element.tagName;
}
attributeMap(element) {
var res = MapWrapper.create();
var elAttrs = element.attributes;
for (var i = 0; i < elAttrs.length; i++) {
var attrib = elAttrs[i];
MapWrapper.set(res, attrib.name, attrib.value);
}
return res;
}
getAttribute(element, attribute:string) {
return element.getAttribute(attribute);
}
setAttribute(element, name:string, value:string) {
element.setAttribute(name, value);
}
removeAttribute(element, attribute:string) {
return element.removeAttribute(attribute);
}
templateAwareRoot(el) {
return el instanceof HTMLTemplateElement ? el.content : el;
}
createHtmlDocument() {
return document.implementation.createHTMLDocument();
}
defaultDoc() {
return document;
}
elementMatches(n, selector:string):boolean {
return n instanceof HTMLElement && n.matches(selector);
}
isTemplateElement(el:any):boolean {
return el instanceof HTMLTemplateElement;
}
isTextNode(node:Node):boolean {
return node.nodeType === Node.TEXT_NODE;
}
isCommentNode(node:Node):boolean {
return node.nodeType === Node.TEXT_NODE;
}
isElementNode(node:Node):boolean {
return node.nodeType === Node.ELEMENT_NODE;
}
hasShadowRoot(node):boolean {
return node instanceof HTMLElement && isPresent(node.shadowRoot);
}
importIntoDoc(node:Node) {
return document.importNode(node, true);
}
isPageRule(rule) {
return rule.type === CSSRule.PAGE_RULE;
}
isStyleRule(rule) {
return rule.type === CSSRule.STYLE_RULE;
}
isMediaRule(rule) {
return rule.type === CSSRule.MEDIA_RULE;
}
isKeyframesRule(rule) {
return rule.type === CSSRule.KEYFRAMES_RULE;
}
}

231
modules/angular2/src/dom/dom_adapter.js vendored Normal file
View File

@ -0,0 +1,231 @@
import {ABSTRACT, BaseException} from 'angular2/src/facade/lang';
export var DOM:DomAdapter;
export function setRootDomAdapter(adapter:DomAdapter) {
DOM = adapter;
}
function _abstract() {
return new BaseException('This method is abstract');
}
/**
* Provides DOM operations in an environment-agnostic way.
*/
@ABSTRACT()
export class DomAdapter {
get attrToPropMap():Map {
throw _abstract();
}
parse(templateHtml:string) {
throw _abstract();
}
query(selector) {
throw _abstract();
}
querySelector(el, selector:string) {
throw _abstract();
}
querySelectorAll(el, selector:string):List {
throw _abstract();
}
on(el, evt, listener) {
throw _abstract();
}
dispatchEvent(el, evt) {
throw _abstract();
}
createMouseEvent(eventType) {
throw _abstract();
}
createEvent(eventType) {
throw _abstract();
}
getInnerHTML(el) {
throw _abstract();
}
getOuterHTML(el) {
throw _abstract();
}
nodeName(node):string {
throw _abstract();
}
nodeValue(node):string {
throw _abstract();
}
type(node):string {
throw _abstract();
}
content(node) {
throw _abstract();
}
firstChild(el) {
throw _abstract();
}
nextSibling(el) {
throw _abstract();
}
parentElement(el) {
throw _abstract();
}
childNodes(el):List {
throw _abstract();
}
childNodesAsList(el):List {
throw _abstract();
}
clearNodes(el) {
throw _abstract();
}
appendChild(el, node) {
throw _abstract();
}
removeChild(el, node) {
throw _abstract();
}
remove(el) {
throw _abstract();
}
insertBefore(el, node) {
throw _abstract();
}
insertAllBefore(el, nodes) {
throw _abstract();
}
insertAfter(el, node) {
throw _abstract();
}
setInnerHTML(el, value) {
throw _abstract();
}
getText(el) {
throw _abstract();
}
setText(el, value:string) {
throw _abstract();
}
getValue(el) {
throw _abstract();
}
setValue(el, value:string) {
throw _abstract();
}
getChecked(el) {
throw _abstract();
}
setChecked(el, value:boolean) {
throw _abstract();
}
createTemplate(html) {
throw _abstract();
}
createElement(tagName, doc = null) {
throw _abstract();
}
createTextNode(text: string, doc = null) {
throw _abstract();
}
createScriptTag(attrName:string, attrValue:string, doc = null) {
throw _abstract();
}
createStyleElement(css:string, doc = null) {
throw _abstract();
}
createShadowRoot(el) {
throw _abstract();
}
getShadowRoot(el) {
throw _abstract();
}
clone(node) {
throw _abstract();
}
hasProperty(element, name:string) {
throw _abstract();
}
getElementsByClassName(element, name:string) {
throw _abstract();
}
getElementsByTagName(element, name:string) {
throw _abstract();
}
classList(element):List {
throw _abstract();
}
addClass(element, classname:string) {
throw _abstract();
}
removeClass(element, classname:string) {
throw _abstract();
}
hasClass(element, classname:string) {
throw _abstract();
}
setStyle(element, stylename:string, stylevalue:string) {
throw _abstract();
}
removeStyle(element, stylename:string) {
throw _abstract();
}
getStyle(element, stylename:string) {
throw _abstract();
}
tagName(element):string {
throw _abstract();
}
attributeMap(element) {
throw _abstract();
}
getAttribute(element, attribute:string) {
throw _abstract();
}
setAttribute(element, name:string, value:string) {
throw _abstract();
}
removeAttribute(element, attribute:string) {
throw _abstract();
}
templateAwareRoot(el) {
throw _abstract();
}
createHtmlDocument() {
throw _abstract();
}
defaultDoc() {
throw _abstract();
}
elementMatches(n, selector:string):boolean {
throw _abstract();
}
isTemplateElement(el:any):boolean {
throw _abstract();
}
isTextNode(node):boolean {
throw _abstract();
}
isCommentNode(node):boolean {
throw _abstract();
}
isElementNode(node):boolean {
throw _abstract();
}
hasShadowRoot(node):boolean {
throw _abstract();
}
importIntoDoc(node) {
throw _abstract();
}
isPageRule(rule) {
throw _abstract();
}
isStyleRule(rule) {
throw _abstract();
}
isMediaRule(rule) {
throw _abstract();
}
isKeyframesRule(rule) {
throw _abstract();
}
}

View File

@ -0,0 +1,229 @@
library angular2.dom.html5adapter;
import 'dom_adapter.dart';
import 'package:html5lib/parser.dart' as parser;
import 'package:html5lib/dom.dart';
class Html5LibDomAdapter implements DomAdapter {
static void makeCurrent() {
setRootDomAdapter(new Html5LibDomAdapter());
}
Element parse(String templateHtml) => parser.parse(templateHtml).firstChild;
query(selector) {
throw 'not implemented';
}
querySelector(el, String selector) {
throw 'not implemented';
}
List querySelectorAll(el, String selector) {
throw 'not implemented';
}
on(el, evt, listener) {
throw 'not implemented';
}
dispatchEvent(el, evt) {
throw 'not implemented';
}
createMouseEvent(eventType) {
throw 'not implemented';
}
createEvent(eventType) {
throw 'not implemented';
}
getInnerHTML(el) {
return el.innerHtml;
}
getOuterHTML(el) {
throw 'not implemented';
}
String nodeName(node) {
throw 'not implemented';
}
String nodeValue(node) {
throw 'not implemented';
}
String type(node) {
throw 'not implemented';
}
content(TemplateElement node) {
throw 'not implemented';
}
firstChild(el) => el is NodeList
? el.first
: el.firstChild;
nextSibling(el) {
final parentNode = el.parentNode;
if (parentNode == null) return null;
final siblings = parentNode.nodes;
final index = siblings.indexOf(el);
if (index < siblings.length - 1) {
return siblings[index + 1];
}
return null;
}
parentElement(el) {
throw 'not implemented';
}
List childNodes(el) {
throw 'not implemented';
}
List childNodesAsList(el) {
throw 'not implemented';
}
clearNodes(el) {
throw 'not implemented';
}
appendChild(el, node) {
throw 'not implemented';
}
removeChild(el, node) {
throw 'not implemented';
}
remove(el) {
throw 'not implemented';
}
insertBefore(el, node) {
throw 'not implemented';
}
insertAllBefore(el, nodes) {
throw 'not implemented';
}
insertAfter(el, node) {
throw 'not implemented';
}
setInnerHTML(el, value) {
throw 'not implemented';
}
getText(el) {
throw 'not implemented';
}
setText(el, String value) {
throw 'not implemented';
}
getValue(el) {
throw 'not implemented';
}
setValue(el, String value) {
throw 'not implemented';
}
getChecked(el) {
throw 'not implemented';
}
setChecked(el, bool value) {
throw 'not implemented';
}
createTemplate(html) {
return createElement('template')
..innerHtml = html;
}
createElement(tagName, [doc]) {
return new Element.tag(tagName);
}
createTextNode(String text, [doc]) {
throw 'not implemented';
}
createScriptTag(String attrName, String attrValue, [doc]) {
throw 'not implemented';
}
createStyleElement(String css, [doc]) {
throw 'not implemented';
}
clone(node) {
throw 'not implemented';
}
hasProperty(element, String name) {
throw 'not implemented';
}
getElementsByClassName(element, String name) {
throw 'not implemented';
}
getElementsByTagName(element, String name) {
throw 'not implemented';
}
List classList(element) {
throw 'not implemented';
}
addClass(element, String classname) {
throw 'not implemented';
}
removeClass(element, String classname) {
throw 'not implemented';
}
hasClass(element, String classname) =>
element.classes.contains(classname);
setStyle(element, String stylename, String stylevalue) {
throw 'not implemented';
}
removeStyle(element, String stylename) {
throw 'not implemented';
}
getStyle(element, String stylename) {
throw 'not implemented';
}
String tagName(element) => element.localName;
attributeMap(element) => element.attributes;
getAttribute(element, String attribute) {
throw 'not implemented';
}
setAttribute(element, String name, String value) {
throw 'not implemented';
}
removeAttribute(element, String attribute) {
throw 'not implemented';
}
templateAwareRoot(el) => isTemplateElement(el)
? el.nodes
: el;
createHtmlDocument() {
throw 'not implemented';
}
defaultDoc() {
throw 'not implemented';
}
bool elementMatches(n, String selector) {
throw 'not implemented';
}
bool isTemplateElement(Element el) {
return el != null && el.localName.toLowerCase() == 'template';
}
bool isTextNode(node) {
throw 'not implemented';
}
bool isCommentNode(node) {
throw 'not implemented';
}
bool isElementNode(node) => node is Element;
bool hasShadowRoot(node) {
throw 'not implemented';
}
importIntoDoc(node) {
throw 'not implemented';
}
isPageRule(rule) {
throw 'not implemented';
}
isStyleRule(rule) {
throw 'not implemented';
}
isMediaRule(rule) {
throw 'not implemented';
}
isKeyframesRule(rule) {
throw 'not implemented';
}
}

View File

@ -0,0 +1,21 @@
/**
* Dart version of browser APIs. This library depends on 'dart:html' and
* therefore can only run in the browser.
*/
import 'dart:js' show context;
export 'dart:html' show
document,
location,
window,
Element,
Node;
final _gc = context['gc'];
void gc() {
if (_gc != null) {
_gc.apply(const []);
}
}

View File

@ -0,0 +1,10 @@
/**
* JS version of browser APIs. This library can only run in the browser.
*/
var win = window;
export {win as window};
export var document = window.document;
export var location = window.location;
export var gc = window.gc ? () => window.gc() : () => null;

View File

@ -67,7 +67,7 @@ class StringMapWrapper {
static void forEach(Map m, fn(v, k)) {
m.forEach((k, v) => fn(v, k));
}
static HashMap merge(HashMap a, HashMap b) {
static HashMap merge(Map a, Map b) {
var m = new HashMap.from(a);
b.forEach((k, v) => m[k] = v);
return m;

View File

@ -1,210 +0,0 @@
library angular.core.facade.dom;
import 'dart:html';
import 'dart:js' show JsObject, context;
export 'dart:html' show
CssRule,
CssKeyframesRule,
document,
DocumentFragment,
Element,
location,
Node,
ShadowRoot,
StyleElement,
TemplateElement,
InputElement,
AnchorElement,
Text,
window,
attrToPropMap;
// TODO(tbosch): Is there a builtin one? Why is Dart
// removing unknown elements by default?
class IdentitySanitizer implements NodeTreeSanitizer {
void sanitizeTree(Node node) {}
}
final _window = context['window'];
final _gc = context['gc'];
void gc() {
if (_gc != null) {
_gc.apply(const []);
}
}
final identitySanitizer = new IdentitySanitizer();
// override JS logic of attribute to property mapping
var attrToPropMap = {
"inner-html": "innerHtml"
};
class DOM {
static query(String selector) => document.querySelector(selector);
static Element querySelector(el, String selector) =>
el.querySelector(selector);
static ElementList querySelectorAll(el, String selector) =>
el.querySelectorAll(selector);
static void on(EventTarget element, String event, callback(arg)) {
// due to https://code.google.com/p/dart/issues/detail?id=17406
// addEventListener misses zones so we use element.on.
element.on[event].listen(callback);
}
static void dispatchEvent(EventTarget el, Event evt) {
el.dispatchEvent(evt);
}
static MouseEvent createMouseEvent(String eventType) =>
new MouseEvent(eventType, canBubble: true);
static createEvent(eventType) =>
new Event(eventType, canBubble: true);
static String getInnerHTML(Element el) => el.innerHtml;
static String getOuterHTML(Element el) => el.outerHtml;
static void setInnerHTML(Element el, String value) {
el.innerHtml = value;
}
static String nodeName(Node el) => el.nodeName;
static String nodeValue(Node el) => el.nodeValue;
static String type(InputElement el) => el.type;
static Node content(TemplateElement el) => el.content;
static Node firstChild(el) => el.firstChild;
static Node nextSibling(Node el) => el.nextNode;
static Element parentElement(Node el) => el.parent;
static List<Node> childNodes(Node el) => el.childNodes;
static List childNodesAsList(Node el) => childNodes(el).toList();
static void clearNodes(Node el) {
el.nodes = const [];
}
static void appendChild(Node el, Node node) {
el.append(node);
}
static void removeChild(Element el, Node node) {
node.remove();
}
static Element remove(Element el) {
return el..remove();
}
static insertBefore(Node el, node) {
el.parentNode.insertBefore(node, el);
}
static void insertAllBefore(Node el, Iterable<Node> nodes) {
el.parentNode.insertAllBefore(nodes, el);
}
static void insertAfter(Node el, Node node) {
el.parentNode.insertBefore(node, el.nextNode);
}
static String getText(Node el) => el.text;
static void setText(Node el, String value) {
el.text = value;
}
static String getValue(InputElement el) => el.value;
static void setValue(InputElement el, String value) {
el.value = value;
}
static bool getChecked(InputElement el) => el.checked;
static void setChecked(InputElement el, bool isChecked) {
el.checked = isChecked;
}
static TemplateElement createTemplate(String html) {
var t = new TemplateElement();
t.setInnerHtml(html, treeSanitizer: identitySanitizer);
return t;
}
static Element createElement(String tagName, [HtmlDocument doc = null]) {
if (doc == null) doc = document;
return doc.createElement(tagName);
}
static createTextNode(String text, [HtmlDocument doc = null]) {
return new Text(text);
}
static createScriptTag(String attrName, String attrValue,
[HtmlDocument doc = null]) {
if (doc == null) doc = document;
var el = doc.createElement("SCRIPT");
el.setAttribute(attrName, attrValue);
return el;
}
static StyleElement createStyleElement(String css, [HtmlDocument doc = null]) {
if (doc == null) doc = document;
var el = doc.createElement("STYLE");
el.text = css;
return el;
}
static ShadowRoot createShadowRoot(Element el) => el.createShadowRoot();
static ShadowRoot getShadowRoot(Element el) => el.shadowRoot;
static clone(Node node) => node.clone(true);
static bool hasProperty(Element element, String name) =>
new JsObject.fromBrowserObject(element).hasProperty(name);
static List<Node> getElementsByClassName(Element element, String name) =>
element.getElementsByClassName(name);
static List<Node> getElementsByTagName(Element element, String name) =>
element.querySelectorAll(name);
static List<String> classList(Element element) => element.classes.toList();
static void addClass(Element element, String classname) {
element.classes.add(classname);
}
static void removeClass(Element element, String classname) {
element.classes.remove(classname);
}
static bool hasClass(Element element, String classname) =>
element.classes.contains(classname);
static void setStyle(Element element, String stylename, String stylevalue) {
element.style.setProperty(stylename, stylevalue);
}
static void removeStyle(Element element, String stylename) {
element.style.removeProperty(stylename);
}
static String getStyle(Element element, String stylename) {
return element.style.getPropertyValue(stylename);
}
static String tagName(Element element) => element.tagName;
static Map<String, String> attributeMap(Element element) =>
element.attributes;
static String getAttribute(Element element, String attribute) =>
element.getAttribute(attribute);
static void setAttribute(Element element, String name, String value) {
element.setAttribute(name, value);
}
static void removeAttribute(Element element, String name) {
//there is no removeAttribute method as of now in Dart:
//https://code.google.com/p/dart/issues/detail?id=19934
element.attributes.remove(name);
}
static Node templateAwareRoot(Element el) =>
el is TemplateElement ? el.content : el;
static HtmlDocument createHtmlDocument() =>
document.implementation.createHtmlDocument('fakeTitle');
static HtmlDocument defaultDoc() => document;
static bool elementMatches(n, String selector) =>
n is Element && n.matches(selector);
static bool isTemplateElement(Element el) =>
el is TemplateElement;
static bool isTextNode(Node node) =>
node.nodeType == Node.TEXT_NODE;
static bool isElementNode(Node node) =>
node.nodeType == Node.ELEMENT_NODE;
static Node importIntoDoc(Node node) {
return document.importNode(node, true);
}
}
class CSSRuleWrapper {
static bool isPageRule(CssRule rule) => rule is CssPageRule;
static bool isStyleRule(CssRule rule) => rule is CssStyleRule;
static bool isMediaRule(CssRule rule) => rule is CssMediaRule;
static bool isKeyframesRule(CssRule rule) => rule is CssKeyframesRule;
}

View File

@ -1,250 +0,0 @@
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
export var window = frames.window;
export var DocumentFragment = window.DocumentFragment;
export var Node = window.Node;
export var NodeList = window.NodeList;
export var Text = window.Text;
export var Element = window.HTMLElement;
export var AnchorElement = window.HTMLAnchorElement;
export var TemplateElement = window.HTMLTemplateElement;
export var StyleElement = window.HTMLStyleElement;
export var ShadowRoot = window.ShadowRoot;
export var document = window.document;
export var location = window.location;
export var gc = window.gc ? () => window.gc() : () => null;
export var CssRule = window.CSSRule;
export var CssKeyframesRule = window.CSSKeyframesRule;
export var attrToPropMap = {};
export class DOM {
static query(selector) {
return document.querySelector(selector);
}
static querySelector(el, selector:string):Node {
return el.querySelector(selector);
}
static querySelectorAll(el, selector:string):NodeList {
return el.querySelectorAll(selector);
}
static on(el, evt, listener) {
el.addEventListener(evt, listener, false);
}
static dispatchEvent(el, evt) {
el.dispatchEvent(evt);
}
static createMouseEvent(eventType) {
var evt = new MouseEvent(eventType);
evt.initEvent(eventType, true, true);
return evt;
}
static createEvent(eventType) {
return new Event(eventType, true);
}
static getInnerHTML(el) {
return el.innerHTML;
}
static getOuterHTML(el) {
return el.outerHTML;
}
static nodeName(node:Node):string {
return node.nodeName;
}
static nodeValue(node:Node):string {
return node.nodeValue;
}
static type(node:Element):string {
return node.type;
}
static content(node:TemplateElement):Node {
return node.content;
}
static firstChild(el):Node {
return el.firstChild;
}
static nextSibling(el):Node {
return el.nextSibling;
}
static parentElement(el) {
return el.parentElement;
}
static childNodes(el):NodeList {
return el.childNodes;
}
static childNodesAsList(el):List {
var childNodes = el.childNodes;
var res = ListWrapper.createFixedSize(childNodes.length);
for (var i=0; i<childNodes.length; i++) {
res[i] = childNodes[i];
}
return res;
}
static clearNodes(el) {
el.innerHTML = "";
}
static appendChild(el, node) {
el.appendChild(node);
}
static removeChild(el, node) {
el.removeChild(node);
}
static remove(el: Element): Element {
var parent = el.parentNode;
parent.removeChild(el);
return el;
}
static insertBefore(el, node) {
el.parentNode.insertBefore(node, el);
}
static insertAllBefore(el, nodes) {
ListWrapper.forEach(nodes, (n) => {
el.parentNode.insertBefore(n, el);
});
}
static insertAfter(el, node) {
el.parentNode.insertBefore(node, el.nextSibling);
}
static setInnerHTML(el, value) {
el.innerHTML = value;
}
static getText(el: Element) {
return el.textContent;
}
// TODO(vicb): removed Element type because it does not support StyleElement
static setText(el, value:string) {
el.textContent = value;
}
static getValue(el: Element) {
return el.value;
}
static setValue(el: Element, value:string) {
el.value = value;
}
static getChecked(el: Element) {
return el.checked;
}
static setChecked(el: Element, value:boolean) {
el.checked = value;
}
static createTemplate(html) {
var t = document.createElement('template');
t.innerHTML = html;
return t;
}
static createElement(tagName, doc=document) {
return doc.createElement(tagName);
}
static createTextNode(text: string, doc=document) {
return doc.createTextNode(text);
}
static createScriptTag(attrName:string, attrValue:string, doc=document) {
var el = doc.createElement("SCRIPT");
el.setAttribute(attrName, attrValue);
return el;
}
static createStyleElement(css:string, doc=document):StyleElement {
var style = doc.createElement('STYLE');
style.innerText = css;
return style;
}
static createShadowRoot(el: Element): ShadowRoot {
return el.createShadowRoot();
}
static getShadowRoot(el: Element): ShadowRoot {
return el.shadowRoot;
}
static clone(node:Node) {
return node.cloneNode(true);
}
static hasProperty(element:Element, name:string) {
return name in element;
}
static getElementsByClassName(element:Element, name:string) {
return element.getElementsByClassName(name);
}
static getElementsByTagName(element:Element, name:string) {
return element.getElementsByTagName(name);
}
static classList(element:Element):List {
return Array.prototype.slice.call(element.classList, 0);
}
static addClass(element:Element, classname:string) {
element.classList.add(classname);
}
static removeClass(element:Element, classname:string) {
element.classList.remove(classname);
}
static hasClass(element:Element, classname:string) {
return element.classList.contains(classname);
}
static setStyle(element:Element, stylename:string, stylevalue:string) {
element.style[stylename] = stylevalue;
}
static removeStyle(element:Element, stylename:string) {
element.style[stylename] = null;
}
static getStyle(element:Element, stylename:string) {
return element.style[stylename];
}
static tagName(element:Element):string {
return element.tagName;
}
static attributeMap(element:Element) {
var res = MapWrapper.create();
var elAttrs = element.attributes;
for (var i = 0; i < elAttrs.length; i++) {
var attrib = elAttrs[i];
MapWrapper.set(res, attrib.name, attrib.value);
}
return res;
}
static getAttribute(element:Element, attribute:string) {
return element.getAttribute(attribute);
}
static setAttribute(element:Element, name:string, value:string) {
element.setAttribute(name, value);
}
static removeAttribute(element:Element, attribute:string) {
return element.removeAttribute(attribute);
}
static templateAwareRoot(el:Element):Node {
return el instanceof TemplateElement ? el.content : el;
}
static createHtmlDocument() {
return document.implementation.createHTMLDocument();
}
static defaultDoc() {
return document;
}
static elementMatches(n, selector:string):boolean {
return n instanceof Element && n.matches(selector);
}
static isTemplateElement(el:any):boolean {
return el instanceof TemplateElement;
}
static isTextNode(node:Node):boolean {
return node.nodeType === Node.TEXT_NODE;
}
static isElementNode(node:Node):boolean {
return node.nodeType === Node.ELEMENT_NODE;
}
static importIntoDoc(node:Node) {
return document.importNode(node, true);
}
}
export class CSSRuleWrapper {
static isPageRule(rule) {
return rule.type === CSSRule.PAGE_RULE;
}
static isStyleRule(rule) {
return rule.type === CSSRule.STYLE_RULE;
}
static isMediaRule(rule) {
return rule.type === CSSRule.MEDIA_RULE;
}
static isKeyframesRule(rule) {
return rule.type === CSSRule.KEYFRAMES_RULE;
}
}

View File

@ -1,5 +1,5 @@
import {Template, Component, Decorator, NgElement, Ancestor, onChange} from 'angular2/core';
import {DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {isBlank, isPresent, CONST} from 'angular2/src/facade/lang';
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {ControlGroup, Control} from './model';

View File

@ -1,6 +1,9 @@
import {DOM, document, location} from 'angular2/src/facade/dom';
import {BrowserDomAdapter} from 'angular2/src/dom/browser_adapter';
import {document} from 'angular2/src/facade/browser';
import {NumberWrapper, BaseException, isBlank} from 'angular2/src/facade/lang';
var DOM = new BrowserDomAdapter();
export function getIntParameter(name:string) {
return NumberWrapper.parseInt(getStringParameter(name), 10);
}

View File

@ -1,13 +1,14 @@
library test_lib.test_lib;
import 'package:guinness/guinness_html.dart' as gns;
export 'package:guinness/guinness_html.dart' hide Expect, expect, NotExpect, beforeEach, it, iit;
import 'package:guinness/guinness.dart' as gns;
export 'package:guinness/guinness.dart' hide Expect, expect, NotExpect, beforeEach, it, iit;
import 'package:unittest/unittest.dart' hide expect;
import 'dart:mirrors';
import 'dart:async';
import 'package:angular2/src/reflection/reflection.dart';
import 'package:angular2/src/reflection/reflection_capabilities.dart';
import 'package:collection/equality.dart';
import 'package:angular2/src/dom/dom_adapter.dart' show DOM;
bool IS_DARTIUM = true;
@ -29,6 +30,7 @@ class Expect extends gns.Expect {
void toBePromise() => _expect(actual is Future, equals(true));
void toImplement(expected) => toBeA(expected);
void toBeNaN() => _expect(double.NAN.compareTo(actual) == 0, equals(true));
void toHaveText(expected) => _expect(elementText(actual), expected);
Function get _expect => gns.guinness.matchers.expect;
}
@ -43,7 +45,6 @@ class NotExpect extends gns.NotExpect {
}
beforeEach(fn) {
gns.guinnessEnableHtmlMatchers();
gns.beforeEach(_enableReflection(fn));
}
@ -137,3 +138,32 @@ class _FixedObjToData {
});
}
}
String elementText(n) {
hasNodes(n) {
var children = DOM.childNodes(n);
return children != null && children.length > 0;
}
if (n is Iterable) {
return n.map((nn) => elementText(nn)).join("");
}
if (DOM.isCommentNode(n)) {
return '';
}
if (DOM.isElementNode(n) && DOM.tagName(n) == 'CONTENT') {
return elementText(n.getDistributedNodes());
}
if (DOM.hasShadowRoot(n)) {
return elementText(DOM.childNodesAsList(n.shadowRoot));
}
if (hasNodes(n)) {
return elementText(DOM.childNodesAsList(n));
}
return DOM.getText(n);
}

View File

@ -1,4 +1,4 @@
import {DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
export {proxy} from 'rtts_assert/rtts_assert';
export var describe = window.describe;
@ -150,7 +150,6 @@ export class SpyObject {
function elementText(n) {
var hasShadowRoot = (n) => n instanceof Element && n.shadowRoot;
var hasNodes = (n) => {var children = DOM.childNodes(n); return children && children.length > 0;}
if (n instanceof Comment) return '';
@ -158,8 +157,8 @@ function elementText(n) {
if (n instanceof Array) return n.map((nn) => elementText(nn)).join("");
if (n instanceof Element && DOM.tagName(n) == 'CONTENT')
return elementText(Array.prototype.slice.apply(n.getDistributedNodes()));
if (hasShadowRoot(n)) return elementText(DOM.childNodesAsList(n.shadowRoot));
if (DOM.hasShadowRoot(n)) return elementText(DOM.childNodesAsList(n.shadowRoot));
if (hasNodes(n)) return elementText(DOM.childNodesAsList(n));
return n.textContent;
}
}

View File

@ -1,5 +1,5 @@
import {List, ListWrapper} from 'angular2/src/facade/collection';
import {DOM} from 'angular2/src/facade/dom';
import {DOM} from 'angular2/src/dom/dom_adapter';
import {isPresent} from 'angular2/src/facade/lang';
export class Log {