2015-03-23 14:10:55 -07:00
|
|
|
import {List, Map, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
|
|
|
import {DOM} from 'angular2/src/dom/dom_adapter';
|
2015-05-20 17:19:46 -07:00
|
|
|
import {isBlank, isPresent, Type, StringJoiner, assertionsEnabled} from 'angular2/src/facade/lang';
|
2015-03-23 14:10:55 -07:00
|
|
|
|
|
|
|
import {ProtoViewBuilder, ElementBinderBuilder} from '../view/proto_view_builder';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Collects all data that is needed to process an element
|
|
|
|
* in the compile process. Fields are filled
|
|
|
|
* by the CompileSteps starting out with the pure HTMLElement.
|
|
|
|
*/
|
|
|
|
export class CompileElement {
|
2015-06-12 23:11:11 +02:00
|
|
|
_attrs: Map<string, string> = null;
|
|
|
|
_classList: List<string> = null;
|
|
|
|
isViewRoot: boolean = false;
|
|
|
|
// inherited down to children if they don't have an own protoView
|
|
|
|
inheritedProtoView: ProtoViewBuilder = null;
|
|
|
|
distanceToInheritedBinder: number = 0;
|
|
|
|
// inherited down to children if they don't have an own elementBinder
|
|
|
|
inheritedElementBinder: ElementBinderBuilder = null;
|
|
|
|
compileChildren: boolean = true;
|
2015-05-18 11:57:20 -07:00
|
|
|
elementDescription: string; // e.g. '<div [class]="foo">' : used to provide context in case of
|
|
|
|
// error
|
2015-03-23 14:10:55 -07:00
|
|
|
|
2015-06-12 23:11:11 +02:00
|
|
|
constructor(public element, compilationUnit: string = '') {
|
2015-03-23 14:10:55 -07:00
|
|
|
// description is calculated here as compilation steps may change the element
|
2015-05-18 11:57:20 -07:00
|
|
|
var tplDesc = assertionsEnabled() ? getElementDescription(element) : null;
|
2015-03-23 14:10:55 -07:00
|
|
|
if (compilationUnit !== '') {
|
|
|
|
this.elementDescription = compilationUnit;
|
|
|
|
if (isPresent(tplDesc)) this.elementDescription += ": " + tplDesc;
|
|
|
|
} else {
|
|
|
|
this.elementDescription = tplDesc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-26 11:10:52 -07:00
|
|
|
isBound(): boolean {
|
2015-03-23 14:10:55 -07:00
|
|
|
return isPresent(this.inheritedElementBinder) && this.distanceToInheritedBinder === 0;
|
|
|
|
}
|
|
|
|
|
2015-06-26 11:10:52 -07:00
|
|
|
bindElement(): ElementBinderBuilder {
|
2015-03-23 14:10:55 -07:00
|
|
|
if (!this.isBound()) {
|
|
|
|
var parentBinder = this.inheritedElementBinder;
|
2015-05-18 11:57:20 -07:00
|
|
|
this.inheritedElementBinder =
|
|
|
|
this.inheritedProtoView.bindElement(this.element, this.elementDescription);
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isPresent(parentBinder)) {
|
|
|
|
this.inheritedElementBinder.setParent(parentBinder, this.distanceToInheritedBinder);
|
|
|
|
}
|
|
|
|
this.distanceToInheritedBinder = 0;
|
|
|
|
}
|
|
|
|
return this.inheritedElementBinder;
|
|
|
|
}
|
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
refreshAttrs() { this._attrs = null; }
|
2015-03-23 14:10:55 -07:00
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
attrs(): Map<string, string> {
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isBlank(this._attrs)) {
|
|
|
|
this._attrs = DOM.attributeMap(this.element);
|
|
|
|
}
|
|
|
|
return this._attrs;
|
|
|
|
}
|
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
refreshClassList() { this._classList = null; }
|
2015-03-23 14:10:55 -07:00
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
classList(): List<string> {
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isBlank(this._classList)) {
|
2015-06-17 11:17:21 -07:00
|
|
|
this._classList = [];
|
2015-03-23 14:10:55 -07:00
|
|
|
var elClassList = DOM.classList(this.element);
|
|
|
|
for (var i = 0; i < elClassList.length; i++) {
|
2015-06-17 11:17:21 -07:00
|
|
|
this._classList.push(elClassList[i]);
|
2015-03-23 14:10:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return this._classList;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// return an HTML representation of an element start tag - without its content
|
|
|
|
// this is used to give contextual information in case of errors
|
2015-05-18 11:57:20 -07:00
|
|
|
function getElementDescription(domElement): string {
|
2015-03-23 14:10:55 -07:00
|
|
|
var buf = new StringJoiner();
|
|
|
|
var atts = DOM.attributeMap(domElement);
|
|
|
|
|
|
|
|
buf.add("<");
|
|
|
|
buf.add(DOM.tagName(domElement).toLowerCase());
|
|
|
|
|
|
|
|
// show id and class first to ease element identification
|
2015-06-17 16:21:40 -07:00
|
|
|
addDescriptionAttribute(buf, "id", atts.get("id"));
|
|
|
|
addDescriptionAttribute(buf, "class", atts.get("class"));
|
2015-03-23 14:10:55 -07:00
|
|
|
MapWrapper.forEach(atts, (attValue, attName) => {
|
2015-05-18 11:57:20 -07:00
|
|
|
if (attName !== "id" && attName !== "class") {
|
|
|
|
addDescriptionAttribute(buf, attName, attValue);
|
|
|
|
}
|
2015-03-23 14:10:55 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
buf.add(">");
|
|
|
|
return buf.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-18 11:57:20 -07:00
|
|
|
function addDescriptionAttribute(buffer: StringJoiner, attName: string, attValue) {
|
2015-03-23 14:10:55 -07:00
|
|
|
if (isPresent(attValue)) {
|
2015-05-18 11:57:20 -07:00
|
|
|
if (attValue.length === 0) {
|
|
|
|
buffer.add(' ' + attName);
|
|
|
|
} else {
|
|
|
|
buffer.add(' ' + attName + '="' + attValue + '"');
|
|
|
|
}
|
2015-03-23 14:10:55 -07:00
|
|
|
}
|
|
|
|
}
|